What is the difference between WHERE and HAVING in SQL?
WHERE filters individual rows before any grouping or aggregation occurs; HAVING filters groups after aggregation. You cannot reference an aggregate function like COUNT() or SUM() in a WHERE clause because those values don't exist yet at that stage of query execution.
How to think about it
WHERE and HAVING both filter rows, but they operate at completely different stages of query execution. The key is the SQL logical processing order.
The position each clause runs in
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
WHERE runs at step 2 — before any groups exist, so aggregate functions like COUNT(*) are meaningless there. HAVING runs at step 4 — after grouping, where aggregates are fully computed.
A concrete example
Imagine you want customers who placed more than 5 orders specifically in 2024:
SELECT customer_id, COUNT(*) AS order_count
FROM orders
WHERE order_year = 2024 -- step 2: discard non-2024 rows early
GROUP BY customer_id
HAVING COUNT(*) > 5; -- step 4: keep only groups big enough
WHERE order_year = 2024 runs first and reduces the row set before grouping — that is the cheap, early filter. HAVING COUNT(*) > 5 then runs on the much smaller set of aggregated groups.
Mixing both in one query is fine and usually correct: use WHERE to reduce rows early (before the aggregation work), then HAVING to filter the result.
When you have no GROUP BY
HAVING without GROUP BY treats the entire result set as one group. This is valid but unusual:
SELECT COUNT(*) FROM orders HAVING COUNT(*) > 1000;
Essentially: “return the count only if there are more than 1000 orders total.”