Beginner: asking questions · Aggregation: GROUP BY and HAVING · topic 16 of 62 · 30 min
Aggregate functions
Explanation
From rows to answers
So far every query returned one result row per table row. But many questions want a single number: How many students are there? What is the total stock value? What is the highest salary? An aggregate function (from "aggregate", to gather together) reads a whole set of rows and returns one value.
| Function | Gives | On STUDENTS marks |
|---|---|---|
| COUNT(*) | Number of rows | 8 |
| COUNT(marks) | Number of rows where marks is not NULL | 7 |
| COUNT(DISTINCT city) | Number of different values | 5 cities |
| SUM(marks) | Total | 504 |
| AVG(marks) | Average (mean) of the non-NULL values | 72 |
| MIN(marks), MAX(marks) | Smallest and largest | 45 and 91 |
SELECT COUNT(*) AS all_students, COUNT(marks) AS with_marks, COUNT(DISTINCT city) AS cities
FROM students;
-- 8 | 7 | 5The three kinds of COUNT
- COUNT(*) counts rows, whatever is in them. Use it for "how many orders", "how many students".
- COUNT(column) counts rows where that column is not NULL. COUNT(email) on SHOP customers gives 4, because two have no email.
- COUNT(DISTINCT column) counts different non-NULL values. COUNT(DISTINCT dept_id) in COMPANY is 4: departments 1 to 4, and Deepak's NULL is not counted.
SUM and expressions
An aggregate can work on an expression, not just a column. The value of all stock is the sum of price × stock over every product:
SELECT SUM(price * stock) AS stock_value FROM products;
-- 169430How NULLs are skipped
SUM, AVG, MIN, MAX and COUNT(column) all ignore NULLs. For SUM that is usually what you want. For AVG it needs thought: AVG(marks) divides the total by the number of students who HAVE marks, not by all students.
SELECT ROUND(AVG(marks), 2) AS avg_marks,
ROUND(AVG(COALESCE(marks, 0)), 2) AS avg_as_zero
FROM students;
-- 72 | 63MIN and MAX are not only for numbers
MIN and MAX work on text and dates too. MIN(name) is the first name in alphabetical order; MAX(hire_date) is the most recent hire, because ISO dates sort correctly as text (module 3).
SELECT MIN(salary) AS lowest, MAX(salary) AS highest,
MIN(hire_date) AS first_hire, MAX(hire_date) AS latest_hire
FROM employees;
-- 45000 | 250000 | 2015-04-01 | 2024-06-01Aggregates over no rows
If WHERE removes every row, COUNT gives 0 but SUM, AVG, MIN and MAX give NULL. SELECT SUM(price) FROM products WHERE category = 'Toys' returns NULL, not 0. Wrap it in COALESCE(SUM(price), 0) when a report must show 0.
You cannot mix rows and aggregates (yet)
SELECT name, MAX(salary) FROM employees asks for many names and one maximum in the same row. Standard SQL rejects it; SQLite runs it and happens to show the name from the row with the maximum, which hides the problem. To get "who earns the most", sort and LIMIT (module 2) or use a subquery (module 6). To get one answer per group, use GROUP BY, the next topic.
Common mistakes
- Using COUNT(column) when you mean COUNT(*), and getting a smaller number because of NULLs.
- Forgetting that AVG skips NULLs. Decide whether missing should count as 0, and use COALESCE if so.
- Showing NULL instead of 0 when no rows match. Use COALESCE(SUM(x), 0).
- Writing COUNT(DISTINCT *): it is not valid. Name the column: COUNT(DISTINCT city).
- Expecting AVG to round. It does not; add ROUND(AVG(x), 2).
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Aggregate functions · 1/7
Many questions want one number, not a list of rows. Aggregate functions gather many rows into one value.
Prefer a video by a teacher? Find free videos on “sql aggregate functions count sum avg min max null tutorial” on YouTube ↗
In real life: The headline numbers on a store dashboard
The top strip of an online store's admin dashboard usually shows a few big numbers: total products, units in stock, the value of that stock, and the cheapest and dearest item. Each is one aggregate query over a table. Teams check that the numbers make sense, for example that COUNT(*) matches the product list, before trusting the charts below.
SELECT COUNT(*) AS products,
SUM(stock) AS units,
SUM(price * stock) AS stock_value,
MIN(price) AS cheapest,
MAX(price) AS dearest
FROM products;Practice (0/4 done)
How many students are there, and how many have marks recorded? Return two columns: all_students and with_marks.
Return the average marks rounded to 2 decimal places, named avg_marks, and the average when a missing mark counts as 0, also rounded to 2, named avg_as_zero.
What is all the stock worth? Return one column, stock_value: the sum of price * stock over all products.
From employees (COMPANY), return the lowest and the highest monthly salary, named lowest and highest.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- GROUP BYAggregation: GROUP BY and HAVING · same module
- HAVING versus WHEREAggregation: GROUP BY and HAVING · same module
- Conditional aggregation and string aggregationAggregation: GROUP BY and HAVING · same module
- Counting and totals: aggregate functionsBackend Development · Databases and SQL basics
- GROUP BY and HAVINGBackend Development · SQL in depth
- OVER and PARTITION BYWindow functions
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
A column has the values 10, NULL, 20. What is AVG of it?
Answer: 15
AVG skips NULL: (10 + 20) / 2 = 15.
customers has 6 rows and 2 have no email. What does COUNT(email) return?
Answer: 4
COUNT(column) counts only values that are not NULL.
No product is in the Toys category. What does SELECT SUM(price) FROM products WHERE category = 'Toys' return?
Answer: NULL
SUM over no rows is NULL (COUNT would be 0). Use COALESCE(SUM(price), 0) to show 0.
Which counts the number of different cities, ignoring NULL?
Answer: COUNT(DISTINCT city)
DISTINCT goes inside the brackets of COUNT.
In SQL Server, an INTEGER column holds 1 and 2. What does AVG return?
Answer: 1
SQL Server returns an integer average for integer input. Use AVG(col * 1.0) there.
A table has 10 rows; the email column is NULL in 3 of them. What is COUNT(email)?Related
Answer: 7
COUNT(column) counts only rows where the column has a value: 10 - 3 = 7.
Why does PostgreSQL reject SELECT city, name, SUM(amount) FROM t GROUP BY city?Related
Answer: name is neither grouped nor aggregated, so one city has many possible names
Each output row is one group. A column must be the same for the whole group (grouped) or combined from it (aggregated).
From GROUP BY and HAVING
students has 8 rows in 5 different cities. How many rows does SELECT city, COUNT(*) FROM students GROUP BY city return?Related
employees has 11 rows. How many rows does SELECT name, AVG(salary) OVER (PARTITION BY dept_id) FROM employees return?Related
Answer: 11
A window function never removes rows; each of the 11 rows gets its department average.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 4 more topics in “Aggregation: GROUP BY and HAVING” before its exam: GROUP BY, HAVING versus WHERE, Conditional aggregation and string aggregation, Writing reports with aggregation.
- Module 4 exam: Aggregation, GROUP BY and HAVING · 15 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, JOINs. 62 topics left in the course before the final exam.