datarekha
SQL Easy Asked at AmazonAsked at GoogleAsked at Meta

What is the difference between WHERE and HAVING in SQL, and when must you use HAVING?

The short answer

WHERE filters individual rows before any grouping occurs; HAVING filters groups after GROUP BY is evaluated. You must use HAVING when the filter condition references an aggregate function like SUM or COUNT.

How to think about it

This one is really a question about timing in SQL’s execution order. WHERE fires on raw rows, before any grouping. HAVING fires on groups, after aggregation. You can’t swap them freely — the engine throws an error the moment you put an aggregate where it doesn’t belong.

SQL evaluates its clauses in a fixed order, and the position of WHERE versus HAVING is the whole answer:

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY

At WHERE time only individual rows exist; at HAVING time the groups are already formed and their aggregate values are computable. So the rule of thumb falls right out:

  • filtering on a raw column value → use WHERE;
  • filtering on an aggregate (COUNT, SUM, AVG, …) → you must use HAVING.

A worked example — both in one query

Here WHERE thins the rows to 2024 orders before grouping, and HAVING keeps only the busy customers after aggregation:

SELECT customer_id, COUNT(*) AS order_count, SUM(amount) AS total
FROM orders
WHERE order_date >= '2024-01-01'   -- per-row: drops the lone 2023 order first
GROUP BY customer_id
HAVING COUNT(*) >= 5;              -- per-group: keeps only customers with 5+ orders
customer_idorder_counttotal
161650

Only customer 1 survives. Customer 2 had just two 2024 orders; customer 3’s single 2023 order was removed by WHERE before grouping, leaving one 2024 order — both fail HAVING COUNT(*) >= 5. The two clauses split the labour cleanly: WHERE chose the rows, HAVING judged the groups.

Push filters as early as you can

For a non-aggregate condition, WHERE and HAVING return the same rows — but WHERE lets the engine discard rows before the expensive grouping, and it can use an index to do so. On a large table that’s the difference between scanning a slice and scanning everything.

Learn it properly WHERE & filtering

Keep practising

All SQL questions

Explore further

Skip to content