✏️ Explanatory Question
Level: Basic to Intermediate — A very common question testing your grasp of filtering vs grouping.
Both WHERE and HAVING filter data, but they operate at different stages of query execution.
SUM() or COUNT().GROUP BY has been applied. It can use aggregate functions.WHERE filters rows before aggregation; HAVING filters groups after aggregation. Use WHERE for raw column conditions and HAVING for conditions on aggregated results.
MySQL processes a query in this order — which is why WHERE runs before HAVING:
| Feature | WHERE | HAVING |
|---|---|---|
| Filters | Rows | Groups |
| Runs | Before GROUP BY | After GROUP BY |
| Aggregate functions | Not allowed | Allowed |
| Used with GROUP BY? | Optional | Usually yes |
| Performance | Faster (reduces rows early) | Runs on grouped data |
-- WHERE filters individual rows BEFORE grouping
SELECT dept_id, COUNT(*) AS emp_count
FROM employees
WHERE salary > 30000 -- row-level filter
GROUP BY dept_id;
-- HAVING filters groups AFTER aggregation
SELECT dept_id, COUNT(*) AS emp_count
FROM employees
GROUP BY dept_id
HAVING COUNT(*) > 5; -- group-level filter
-- Both together: WHERE first, then HAVING
SELECT dept_id, AVG(salary) AS avg_sal
FROM employees
WHERE status = 'Active' -- filter rows first
GROUP BY dept_id
HAVING AVG(salary) > 50000; -- then filter groups