Skip to main content

Aggregate Functions: COUNT, SUM, AVG, MIN, MAX

Aggregate functions collapse many rows into a single computed value. They're the foundation of any analytical query.

FunctionWhat it returns
COUNTNumber of rows (or non-NULL values)
SUMTotal of all values
AVGAverage of all values
MINSmallest value
MAXLargest value
Prior lessons

This lesson pairs closely with GROUP BY and HAVING. The sample dataset is defined in the Introduction to SQL lesson.

Syntax

SELECT
COUNT(*) AS total_rows,
SUM(column) AS total,
AVG(column) AS average,
MIN(column) AS minimum,
MAX(column) AS maximum
FROM table_name;

Examples

Example 1: Overall order statistics

SELECT
COUNT(*) AS total_orders,
COUNT(customer_id) AS orders_with_customer,
SUM(total_amount) AS total_revenue,
AVG(total_amount) AS avg_order_value,
MIN(total_amount) AS smallest_order,
MAX(total_amount) AS largest_order
FROM orders;

Result:

total_ordersorders_with_customertotal_revenueavg_order_valuesmallest_orderlargest_order
10104715.78471.5824.95999.00

Example 2: Revenue and order count per customer

SELECT
customer_id,
COUNT(*) AS order_count,
SUM(total_amount) AS total_spent,
AVG(total_amount) AS avg_order_value,
MAX(total_amount) AS largest_order
FROM orders
GROUP BY customer_id
ORDER BY total_spent DESC;

Result:

customer_idorder_counttotal_spentavg_order_valuelargest_order
321795.00897.50999.00
131407.98469.33999.00
221348.00674.00999.00
5189.9789.9789.97
4274.8537.4349.90

Example 3: MIN and MAX on product prices by category

SELECT
category,
MIN(price) AS cheapest,
MAX(price) AS most_expensive,
AVG(price) AS avg_price
FROM products
GROUP BY category;

Result:

categorycheapestmost_expensiveavg_price
Electronics29.99999.00514.50
Furniture199.00349.00274.00
Stationery4.994.994.99

COUNT(*) vs COUNT(column)

SELECT
COUNT(*) AS all_rows, -- counts every row, including NULLs
COUNT(customer_id) AS non_null_count -- skips rows where customer_id is NULL
FROM orders;

If all customer_id values are non-NULL, both return the same number. If some are NULL, COUNT(customer_id) is smaller.

Common Mistake

AVG ignores NULLs - which can mislead

AVG automatically skips NULL values. If 40% of a column is NULL, AVG computes the average over only the 60% that have values. This may not be what you want.

Use COUNT(*) vs COUNT(column) to check before trusting an average:

SELECT
COUNT(*) AS total_rows,
COUNT(total_amount) AS non_null_rows
FROM orders;

If the two numbers differ, AVG(total_amount) is computing over fewer rows than the table actually has.

Practice

Write a query that returns the total number of orders, total revenue, smallest order amount, and largest order amount across all orders.

Show answer
SELECT
COUNT(*) AS total_orders,
SUM(total_amount) AS total_revenue,
MIN(total_amount) AS smallest_order,
MAX(total_amount) AS largest_order
FROM orders;

Expected result:

total_orderstotal_revenuesmallest_orderlargest_order
104715.7824.95999.00
Donate to this project