SQL HAVING clause to filter groups
Filter groups after aggregation with HAVING, and how it differs from WHERE.
HAVING filters groups after aggregation. It's like WHERE, but for aggregate results.
WHERE vs HAVING
| WHERE | HAVING |
|---|---|
| Filters individual rows | Filters grouped results |
| Runs before GROUP BY | Runs after GROUP BY |
| Can't use aggregates | Can use aggregates |
Basic HAVING
-- Countries with more than 100 users SELECT country, COUNT(*) AS user_count FROM users GROUP BY country HAVING COUNT(*) > 100; -- Customers who spent over $1000 SELECT user_id, SUM(total) AS total_spent FROM orders GROUP BY user_id HAVING SUM(total) > 1000;
WHERE + HAVING Together
-- Active customers with 5+ orders in 2024
SELECT
user_id,
COUNT(*) AS order_count,
SUM(total) AS total_spent
FROM orders
WHERE status = 'completed' -- Filter rows FIRST
AND created_at >= '2024-01-01'
GROUP BY user_id
HAVING COUNT(*) >= 5 -- Filter groups AFTER
ORDER BY total_spent DESC;Execution Order
- 1. FROM / JOIN
- 2. WHERE (filter rows)
- 3. GROUP BY (create groups)
- 4. HAVING (filter groups)
- 5. SELECT (compute columns)
- 6. ORDER BY (sort results)
- 7. LIMIT (restrict output)