Fun with Learning Technology
LearnCoursesQuestionsTracksToolsNewsExplorePractice
Fun with Learning Technology

A new problem, explained clearly, every day.

Subscribe
Learn
  • Lessons
  • Topics
  • News
  • Tools
  • Courses
  • Career tracks
  • Everything
Site
  • About
  • Contact
  • Support
  • Privacy
  • Terms
Get the daily one

One email per new problem. No spam.

Request a tutorial

Requests shape what gets made next.

© 2026 Fun with Learning TechnologyRSS
Home›Courses›SQL›Aggregation Functions — COUNT, SUM, AVG, MIN, MAX

Aggregation

Aggregation Functions — COUNT, SUM, AVG, MIN, MAX

Aggregation functions are mathematical operators designed to reduce large datasets into single, meaningful values based on specific calculations. These functions are essential for deriving business intelligence and summary statistics from raw transactional data. You reach for them whenever you need to answer questions about the 'whole' rather than the 'parts,' such as calculating totals, averages, or identifying extremes.

Counting Rows with COUNT

The COUNT function acts as a tallying mechanism that scans a defined set of rows and returns the total number of non-null occurrences. Unlike other aggregate functions that require numeric input, COUNT can be used on any data type. When you pass a specific column name to COUNT, the engine evaluates the presence of data in that field, effectively ignoring NULL values. However, using COUNT(*) instructs the database to count all rows regardless of the content in individual columns, as it treats the row as a single unit of record. This distinction is vital for accurate reporting: if a column contains missing data points, COUNT(column_name) will yield a smaller result than COUNT(*) for the same dataset. Understanding this behavior allows you to accurately measure population size versus the availability of specific data attributes within your database schema.

-- Counts all rows in the orders table
SELECT COUNT(*) AS total_orders FROM orders;
-- Counts only rows where the shipping_date is not NULL
SELECT COUNT(shipping_date) AS shipped_orders FROM orders;

Calculating Totals with SUM

The SUM function is specifically designed to perform additive calculations on sets of numerical data. When the SQL engine executes a SUM operation, it traverses the specified column, identifies every non-null numerical value, and computes their cumulative total. If the engine encounters a NULL value, it ignores that entry entirely, which prevents the accidental contamination of your results by missing data placeholders. Because this function relies on arithmetic addition, it will throw an error if you attempt to apply it to character strings or non-numeric types. The power of SUM lies in its ability to condense thousands of individual transaction amounts into a single balance. This logic is fundamental for financial reporting, inventory valuation, and any scenario where the magnitude of cumulative resources is the primary objective of your analytical query.

-- Calculates the total revenue across all sales
SELECT SUM(price) AS total_revenue 
FROM sales_data;
-- Sums only the revenue for a specific category
SELECT SUM(price) AS electronics_revenue 
FROM sales_data 
WHERE category = 'Electronics';

Finding Averages with AVG

AVG calculates the mean value by dividing the sum of all non-null entries in a column by the count of those entries. It is a composite function, effectively performing both SUM and COUNT operations internally to derive the central tendency of a dataset. Just like SUM, it treats NULL values as non-existent rather than as zeroes; this is a critical distinction, as including zeroes in a denominator would mathematically deflate the average. By automatically excluding NULLs, the function ensures that the average reflects only the active data points present in your records. This is highly beneficial when dealing with incomplete survey data or sparse sensor inputs where missing readings should not count as neutral values. Using AVG allows you to establish performance benchmarks, identify typical transaction sizes, and normalize large sets of information into comparable metrics.

-- Calculates the average order value
SELECT AVG(order_total) AS average_sale_value 
FROM orders;
-- Calculates average price while ignoring NULL values
SELECT AVG(price) AS avg_item_price 
FROM inventory;

Identifying Extremes with MIN and MAX

MIN and MAX are comparison operators that scan a column to find the lowest and highest values, respectively. These functions work across various data types, including numbers, dates, and even strings, where they rely on alphabetical sorting logic. When processing a column, the engine compares every element to the current minimum or maximum candidate, updating its internal 'best match' until the scan is complete. These functions are indispensable for temporal analysis, such as identifying the earliest or most recent timestamp in an activity log. Because they require a complete scan of the data unless an index is present, their performance is tied to the underlying database structure. By mastering MIN and MAX, you gain the ability to pinpoint outliers, determine the lifespan of records, and define the boundaries of your datasets without needing complex sorting or limiting operations.

-- Finds the earliest and latest order dates
SELECT MIN(order_date) AS first_order, MAX(order_date) AS last_order 
FROM orders;
-- Finds the cheapest and most expensive product
SELECT MIN(price), MAX(price) 
FROM inventory;

Combining Aggregates for Insights

In real-world applications, you rarely rely on a single aggregate function; instead, you combine them to build a comprehensive snapshot of your data. Because all these functions reduce a set to a single scalar value, they can be utilized in the same SELECT statement to generate multi-dimensional summaries simultaneously. This process is efficient because the engine often computes these values during a single pass through the requested data rows. When you combine functions like COUNT, SUM, and AVG, you are essentially creating a report template that summarizes volume, value, and trend in one step. This capability is the foundation of data exploration, allowing you to derive sophisticated insights such as 'number of transactions,' 'total revenue,' and 'average price' in a single query. Mastering this multi-functional approach transforms raw tables into actionable business intelligence dashboards.

-- Combining multiple aggregates in one report
SELECT 
    COUNT(*) AS total_sales, 
    SUM(amount) AS gross_revenue, 
    AVG(amount) AS average_per_sale,
    MIN(amount) AS smallest_sale
FROM transactions;

Key points

  • The COUNT function is unique because it can operate on non-numeric columns to determine the size of a dataset.
  • Using COUNT(*) includes every row in the result, whereas COUNT(column) ignores rows where that specific column is NULL.
  • The SUM function exclusively works on numeric data and safely ignores NULL values during the addition process.
  • AVG is mathematically represented as the total sum divided by the count of non-null entries.
  • Both MIN and MAX are versatile functions that can be applied to dates and strings in addition to numerical values.
  • Aggregate functions effectively reduce large datasets into singular summary values for easier reporting and analysis.
  • NULL values are universally ignored by aggregate functions, which prevents them from skewing mathematical calculations.
  • Multiple aggregate functions can be executed within a single query to provide a multi-faceted summary of your data.

Common mistakes

  • Mistake: Including non-aggregated columns in the SELECT clause without GROUP BY. Why it's wrong: SQL does not know which specific row's value to display for an ungrouped column when multiple rows are collapsed. Fix: Include every non-aggregated column in the GROUP BY clause.
  • Mistake: Using aggregate functions in the WHERE clause. Why it's wrong: WHERE filters rows *before* aggregation occurs, so the database doesn't know the aggregate values yet. Fix: Use the HAVING clause to filter based on results of aggregate functions.
  • Mistake: Assuming COUNT(*) and COUNT(column_name) return the same result. Why it's wrong: COUNT(*) counts every row in the result set, while COUNT(column_name) counts only the rows where the specified column is not NULL. Fix: Use COUNT(*) to count rows, or be specific if excluding NULLs is desired.
  • Mistake: Applying AVG() on a column containing NULLs. Why it's wrong: While AVG() ignores NULLs in its calculation, this can skew results if you intended for NULL to represent a zero value. Fix: Use COALESCE(column, 0) inside the AVG function if you want to treat NULLs as zero.
  • Mistake: Trying to perform arithmetic directly on an aggregate result without proper grouping. Why it's wrong: Aggregates return a single value per group; trying to reference them incorrectly often leads to ambiguity regarding the dataset's scope. Fix: Ensure the logic clearly defines the grouping context before performing operations.

Interview questions

What is the primary purpose of aggregation functions in SQL, and can you list the five most common ones?

Aggregation functions are essential in SQL because they allow you to perform calculations on a set of rows and return a single, summarized value for each group. The five most common functions are COUNT, which returns the number of rows; SUM, which adds up the values in a numeric column; AVG, which calculates the arithmetic mean; MIN, which finds the smallest value; and MAX, which identifies the highest value in a specified dataset. These are critical for data analysis, enabling you to distill thousands of rows into actionable metrics like total sales or average order values.

How does the COUNT() function handle NULL values, and what is the difference between COUNT(*) and COUNT(column_name)?

The behavior of COUNT depends entirely on what you pass as an argument. When you use COUNT(column_name), SQL will ignore any NULL values present in that specific column and only count the rows where data exists. Conversely, COUNT(*) counts every single row in the result set, regardless of whether the columns contain NULL values or not. This is a vital distinction in data integrity, as using COUNT(*) is the standard way to determine the total population size of a table without risking the exclusion of incomplete records.

Can you explain why you cannot simply use a standard column name in a SELECT statement alongside an aggregation function without using a GROUP BY clause?

SQL requires that every non-aggregated column in your SELECT statement must be included in a GROUP BY clause because the engine needs to know how to map the individual rows to the summarized aggregate result. If you select a column like 'department' alongside 'SUM(salary)', the database would not know which specific department's sum to associate with each row, resulting in a logical error. By using GROUP BY, you force the engine to collapse rows into unique buckets based on the non-aggregated column, ensuring every group has a coherent, single calculated value for the aggregate function applied.

Compare using a HAVING clause versus a WHERE clause when filtering data involving aggregation functions.

The fundamental difference is the order of execution in the SQL pipeline. You use a WHERE clause to filter individual rows before the aggregation process begins, effectively reducing the dataset before the calculation starts. In contrast, you use a HAVING clause to filter the results after the grouping and aggregation have already occurred. For example, if you want to find departments where the average salary exceeds $50,000, you must use HAVING, because the average is not calculated until the rows have been grouped. WHERE cannot reference aggregate functions because it evaluates row-by-row before those functions exist.

When calculating the average of a column using AVG(), what should you consider regarding data types and NULL values?

When using AVG(), you must be aware that it automatically excludes NULL values from both the sum of the column and the count of the rows. While this is usually helpful, it can lead to misleading results if you assume NULLs represent zero. Additionally, if the column is an integer, some database systems perform integer division, which can truncate decimals. To ensure precision, you should cast the column to a decimal or float type before calculating the average, ensuring the final result retains its fractional component and accurately represents the mean of the data provided.

How would you write a query to find the 'Top 3' products by sales, and what are the limitations of using MIN or MAX when identifying these records?

To find the top 3 products, you would typically group by product, calculate the total sales using SUM(), and then use an ORDER BY clause combined with a LIMIT or TOP operator. Using only MIN or MAX is limiting because they only return a single outlier value—the absolute lowest or highest. If you need the 'top 3', MIN and MAX are insufficient because they cannot identify the second or third-place values without complex subqueries or window functions. Relying on simple aggregates for ranking is less efficient than using modern window functions like RANK() or DENSE_RANK() which handle ties and offsets more gracefully.

All SQL interview questions →

Check yourself

1. If a column 'score' has values [10, NULL, 20], what will SELECT AVG(score) FROM table return?

  • A.10
  • B.15
  • C.30
  • D.NULL
Show answer

B. 15
AVG() ignores NULL values and calculates the average of [10, 20], which is 15. Option 10 is wrong because it assumes NULL is 0. Option 30 is the sum, not the average. NULL is incorrect because aggregate functions exclude missing data from calculations.

2. Which of the following clauses is used to filter records AFTER an aggregation has been performed?

  • A.WHERE
  • B.GROUP BY
  • C.HAVING
  • D.ORDER BY
Show answer

C. HAVING
HAVING is specifically designed to filter groups created by aggregate functions. WHERE filters row-by-row before aggregation, GROUP BY organizes the data, and ORDER BY sorts the final output.

3. You want to find the number of unique cities in a table. Which syntax is correct?

  • A.COUNT(city)
  • B.COUNT(DISTINCT city)
  • C.DISTINCT COUNT(city)
  • D.SUM(DISTINCT city)
Show answer

B. COUNT(DISTINCT city)
COUNT(DISTINCT city) ensures each city name is counted only once. COUNT(city) counts duplicates. The other options are syntactically incorrect or perform the wrong mathematical operation.

4. Given a table of employees, why would 'SELECT department, MAX(salary) FROM employees' fail in many SQL modes?

  • A.MAX cannot be used on numerical columns.
  • B.The query is missing a GROUP BY clause for the department column.
  • C.MAX must be used with a WHERE clause.
  • D.You cannot select columns alongside aggregate functions.
Show answer

B. The query is missing a GROUP BY clause for the department column.
To select an aggregate alongside a non-aggregated column, the non-aggregated column must appear in the GROUP BY clause. Without it, the engine cannot map the maximum salary to the correct department. The other options are false; MAX works on numbers and can be used without WHERE.

5. What is the result of COUNT(*) on a table containing 10 rows, where 3 rows have a NULL value in the 'price' column?

  • A.3
  • B.7
  • C.10
  • D.13
Show answer

C. 10
COUNT(*) counts all rows regardless of NULL values. Therefore, all 10 rows are counted. 7 would be the result if you used COUNT(price), and 3 is incorrect as it represents only the NULL count.

Take the full SQL quiz →

← PreviousNULL Values and IS NULLNext →GROUP BY and HAVING

SQL

32 lessons, free to read.

All lessons →

Track your progress

Sign in to mark lessons done, score quizzes and keep notes.

Open in the app