MySQL Aggregate Functions

Aggregate functions compute a single summary value across many rows, and they are the foundation of nearly every reporting and analytics query.

What Are Aggregate Functions?

An aggregate function performs a calculation on a set of rows and returns a single value, rather than one value per row. MySQL provides several built-in aggregate functions, including COUNT(), SUM(), AVG(), MIN(), and MAX(), all of which are commonly used to summarize data such as sales totals, average prices, or the number of orders placed.

  • COUNT() — counts the number of rows or non-NULL values
  • SUM() — adds up all the numeric values in a column
  • AVG() — calculates the mean of the numeric values in a column
  • MIN() — finds the smallest value in a column
  • MAX() — finds the largest value in a column

Aggregating an Entire Table

When used without GROUP BY, an aggregate function collapses the entire result set of a query down into a single row, summarizing every row that matched the WHERE clause.

Count how many products are in stock

SELECT COUNT(*) AS TotalProducts
FROM Products;

Aggregating Per Group With GROUP BY

Aggregate functions become far more powerful when combined with GROUP BY, which splits the rows into buckets — one bucket per distinct value in the grouping column — and then applies the aggregate function separately to each bucket. This is how you calculate, for example, the total number of orders placed by each individual customer.

Count orders placed by each customer

SELECT CustomerID, COUNT(OrderID) AS NumberOfOrders
FROM Orders
GROUP BY CustomerID;
Note: Any column in the SELECT list that is not wrapped in an aggregate function must appear in the GROUP BY clause, or MySQL's result becomes ambiguous — in strict SQL mode this raises an error rather than a silently wrong answer.

Filtering Groups With HAVING

WHERE filters individual rows before grouping happens, but it cannot reference an aggregate result. To filter based on an aggregated value — such as only showing customers with more than 5 orders — you need the HAVING clause, which runs after grouping and aggregation are complete.

Only show customers with more than 5 orders

SELECT CustomerID, COUNT(OrderID) AS NumberOfOrders
FROM Orders
GROUP BY CustomerID
HAVING COUNT(OrderID) > 5;
Note: A simple way to remember the difference: WHERE filters rows before aggregation, HAVING filters groups after aggregation.
FunctionPurpose
COUNT()Number of rows or non-NULL values
SUM()Total of numeric values
AVG()Mean of numeric values
MIN() / MAX()Smallest / largest value

Exercise: MySQL Aggregate Functions

What does COUNT(*) return?