SQL GROUP BY and HAVING — Aggregating and Filtering Groups
How to use GROUP BY to aggregate rows and HAVING to filter groups. Covers the difference between WHERE and HAVING, common aggregate functions, and examples.
Detailed Explanation
Grouping and Filtering Aggregates
GROUP BY collapses rows that share a value into a single summary row. HAVING filters those groups after aggregation — it is to GROUP BY what WHERE is to SELECT.
Basic GROUP BY
SELECT department_id, COUNT(*) AS emp_count
FROM employees
GROUP BY department_id;
GROUP BY with HAVING
SELECT department_id, COUNT(*) AS emp_count
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 5;
WHERE vs HAVING
| Clause | Filters | Runs |
|---|---|---|
| WHERE | Individual rows | Before grouping |
| HAVING | Groups | After grouping |
-- WHERE filters rows before grouping
-- HAVING filters groups after aggregation
SELECT department_id, AVG(salary) AS avg_salary
FROM employees
WHERE is_active = true -- filter rows first
GROUP BY department_id
HAVING AVG(salary) > 60000; -- then filter groups
Multiple Aggregate Functions
SELECT
d.name AS department,
COUNT(*) AS headcount,
AVG(e.salary) AS avg_salary,
MIN(e.salary) AS min_salary,
MAX(e.salary) AS max_salary
FROM employees e
JOIN departments d ON e.department_id = d.id
GROUP BY d.name
ORDER BY avg_salary DESC;
Grouping by Multiple Columns
SELECT department_id, job_title, COUNT(*)
FROM employees
GROUP BY department_id, job_title;
Common Mistake
Every column in the SELECT that is not inside an aggregate function must appear in the GROUP BY clause. MySQL's ONLY_FULL_GROUP_BY mode (default since 5.7.5) enforces this.
Use Case
You are building a dashboard that shows summary statistics per group — such as total revenue per product category, average order value per region, or employee count per department.
Try It — SQL Cheat Sheet
Related Topics
SQL Aggregate Functions — COUNT, SUM, AVG, MIN, MAX
Functions
SQL ORDER BY and LIMIT — Sorting and Pagination
Clauses & Filters
SQL SELECT with WHERE Clause — Filtering Rows
DML Commands
SQL JOIN Types — INNER, LEFT, RIGHT, FULL, CROSS
Clauses & Filters
SQL Window Functions — ROW_NUMBER, RANK, LAG, LEAD
Advanced SQL