- Use the five main aggregate functions
- Explain the difference between
COUNT(*),COUNT(column)andCOUNT(DISTINCT column) - Combine aggregates with
WHEREand know howNULLaffects them
A teacher doesn't need every student's score — she needs the class average. A shop owner wants the total sales, not a look at every single order. The answer to such questions is not a list of rows but one number. In SQL these numbers are calculated by aggregate functions.
What is an aggregate function?
A function that takes the values from many rows and calculates one result from them. A regular function (such as ROUND) works on each row separately; an aggregate works on all the rows at once.
| Function | What it returns |
|---|---|
| COUNT(*) | the number of rows |
| COUNT(x) | the number of non-NULL values of x |
| SUM(x) | the sum of the values |
| AVG(x) | the average |
| MIN(x) | the smallest value |
| MAX(x) | the largest value |
COUNT: counting
COUNT has three forms. COUNT(*) counts all rows. COUNT(email) counts only the rows that have a value in email — two students have a NULL email, so the result is 10. COUNT(DISTINCT city) gives the number of different cities.
SELECT COUNT(*) AS students,
COUNT(email) AS with_email,
COUNT(DISTINCT city) AS cities
FROM students;▸ Expected output
students | with_email | cities 12 | 10 | 7
SUM, AVG, MIN and MAX
You can put several aggregates in one query. An average is often a long decimal (here 293.558), so we round it with ROUND. The result is always a single row, because the whole table is summarised as one group.
SELECT SUM(stock) AS total_items,
ROUND(AVG(price), 2) AS avg_price,
MIN(price) AS cheapest,
MAX(price) AS most_expensive
FROM products;▸ Expected output
total_items | avg_price | cheapest | most_expensive 1086 | 293.56 | 3.2 | 1450
MIN and MAX work not only with numbers but also with text and dates. For dates in the YYYY-MM-DD format, MIN gives the earliest date and MAX the latest.
SELECT MIN(order_date) AS first_order,
MAX(order_date) AS last_order
FROM orders;▸ Expected output
first_order | last_order 2025-01-15 | 2025-07-07
Calculating with aggregates
The result of an aggregate is an ordinary number, so you can calculate with it. MAX(age) - MIN(age) gives the difference between the oldest and the youngest age. To find the percentage of students who have an email, divide COUNT(email) by COUNT(*) and multiply by 100. Careful: 100 * 10 / 12 is integer division and gives 83; for the exact result we write 100.0.
SELECT MAX(age) - MIN(age) AS age_range,
100 * COUNT(email) / COUNT(*) AS int_pct,
ROUND(100.0 * COUNT(email) / COUNT(*), 1) AS pct_with_email
FROM students;▸ Expected output
age_range | int_pct | pct_with_email 3 | 83 | 83.3
int_pct lost its fraction because of integer division.Aggregates and WHERE
WHERE works before the aggregate: first the rows are filtered, then the calculation runs only on the rows that are left. Below we take only the enrollments of course 1 (Algebra): 4 students, average score 87.3.
SELECT COUNT(*) AS enrollments,
ROUND(AVG(score), 1) AS avg_score,
MIN(score) AS min_score,
MAX(score) AS max_score
FROM enrollments
WHERE course_id = 1;▸ Expected output
enrollments | avg_score | min_score | max_score 4 | 87.3 | 75 | 97
What is the total value of all goods in the warehouse?
Show solutionHide solution
price * stock.An aggregate can contain an expression:
SUM(price * stock).The DBMS calculates the product for each row first and then adds them up: 40260.6.
SELECT SUM(price * stock) AS warehouse_value
FROM products;▸ Expected output
warehouse_value 40260.6
SELECT AVG(age) AS avg_age
FROM students;▸ Expected output
avg_age 15.5
Summarise course number 1 (Algebra): the number of enrollments (students), the average score rounded to 1 decimal place (avg_score) and the highest score (best).
SELECT COUNT(*) AS students
-- add avg_score and best
FROM enrollments
WHERE course_id = 1;▸ Expected output
students | avg_score | best 4 | 87.3 | 97
For the Electronics category, find the number of products (products), the total number of items in stock (total_stock) and the lowest price (cheapest).
SELECT
-- three aggregates here
FROM products
WHERE category = 'Electronics';▸ Expected output
products | total_stock | cheapest 4 | 63 | 120.5
Key points
- An aggregate function calculates one result from many rows:
COUNT,SUM,AVG,MIN,MAX. COUNT(*)counts all rows,COUNT(x)the non-NULLones andCOUNT(DISTINCT x)the different values.WHEREruns before the aggregate, so only the filtered rows are used.- Aggregates (except
COUNT(*)) skipNULLvalues. - Don't mix an aggregate with a plain column without
GROUP BY— most DBMSs treat it as an error.
Check yourself
10 questions. Every correct answer earns XP.
students, COUNT(*) gives 12 but COUNT(email) gives 10. Why?