What is the difference between WHERE and HAVING in SQL?
WHERE filters rows before grouping; HAVING filters groups after GROUP BY. You cannot use aggregate functions in WHERE.
SQLPostgreSQL
Overview
Both `WHERE` and `HAVING` filter query results, but at different stages. `WHERE` runs before aggregation and filters individual rows. `HAVING` runs after `GROUP BY` and filters the aggregated groups.
Key Points
- β’WHERE: filters rows before GROUP BY is applied. Cannot reference aggregate functions.
- β’HAVING: filters groups after GROUP BY. Can reference aggregates like COUNT, SUM, AVG.
- β’You can use both in the same query: WHERE narrows rows first, then HAVING narrows groups.
- β’HAVING without GROUP BY applies to the whole result set as a single group.
- β’Query execution order: FROM β WHERE β GROUP BY β HAVING β SELECT β ORDER BY β LIMIT.
Examples
WHERE vs HAVING
sql-- WHERE: filter before grouping
-- Only count orders placed in 2025
SELECT customer_id, COUNT(*) AS order_count
FROM orders
WHERE created_at >= '2025-01-01' -- filters rows first
GROUP BY customer_id;
-- HAVING: filter after grouping
-- Only show customers with more than 5 orders
SELECT customer_id, COUNT(*) AS order_count
FROM orders
GROUP BY customer_id
HAVING COUNT(*) > 5; -- filters groupsUsing both WHERE and HAVING together
sql-- Customers with more than 5 paid orders in 2025
SELECT customer_id, COUNT(*) AS paid_orders
FROM orders
WHERE status = 'paid'
AND created_at >= '2025-01-01'
GROUP BY customer_id
HAVING COUNT(*) > 5
ORDER BY paid_orders DESC;Pro Tip
A quick mental model: WHERE is for rows, HAVING is for groups. If you catch yourself trying to put `SUM(...)` or `COUNT(...)` in a WHERE clause, that's a sign you need HAVING instead.