SQL GROUP BY and HAVING, Explained with Examples
GROUP BY turns many rows into one row per group, computing aggregates like SUM or COUNT for each. HAVING then filters those groups. Together they answer "per category" questions.
▶ Open the GROUP BY + HAVING example in SQL Visualizer
GROUP BY: one row per group
To get total revenue per genre, group the movies by genre and sum within each group:
SELECT genre, SUM(revenue) AS total_revenue
FROM movies
GROUP BY genre
ORDER BY total_revenue DESCAggregate functions
COUNT(*)— number of rows in the groupSUM(x)/AVG(x)— total / average of a columnMIN(x)/MAX(x)— smallest / largest value
HAVING: filter the groups
A WHERE clause filters rows before grouping and cannot see aggregates. To filter on an aggregate — say, keep only genres whose total revenue exceeds 1000 — use HAVING, which runs after grouping:
SELECT genre, SUM(revenue) AS total_revenue
FROM movies
GROUP BY genre
HAVING SUM(revenue) > 1000
ORDER BY total_revenue DESCFor the precise difference between the two filters, read WHERE vs HAVING.
Where it sits in the query
GROUP BY runs after WHERE and before SELECT; HAVING sits between them. See the complete SQL execution order.