SQL: WHERE filters rows, HAVING filters groups

WHERE runs before grouping, so it cannot see an aggregate. HAVING runs after, so it can - and putting the condition in the wrong one is either an error or a different answer.

Code
-- rows first, then group
SELECT customer_id, COUNT(*) AS n
  FROM orders
 WHERE status = 'PAID'          -- per row
 GROUP BY customer_id
HAVING COUNT(*) > 3;            -- per group
Output
customer_id | n
          7 | 5
         12 | 4

-- WHERE COUNT(*) > 3 is an error: aggregates do not exist yet.
Advertisement

Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.

Published 2026-08-25