GROUP BY groups rows for per-group aggregation.
HAVING
Filters groups after aggregation. Can use aggregate functions.
GROUP BY groups rows for per-group aggregation.
Filters groups after aggregation. Can use aggregate functions.
SELECT country, COUNT(*) AS user_count FROM users GROUP BY country; SELECT country, COUNT(*) FROM users GROUP BY country HAVING COUNT(*) > 10; SELECT department, AVG(salary) FROM employees GROUP BY department HAVING AVG(salary) > 50000 ORDER BY AVG(salary) DESC;
-- Count users per city SELECT city, COUNT(*) AS total FROM users GROUP BY city; -- HAVING filters groups (WHERE filters rows) SELECT city, AVG(age) AS avg_age FROM users GROUP BY city HAVING AVG(age) > 25 ORDER BY avg_age DESC; -- Group by with multiple columns SELECT department, job_title, COUNT(*) AS staff FROM employees GROUP BY department, job_title HAVING COUNT(*) > 2;
Categories with more than 10 products.
SELECT category, COUNT(*) FROM products
GROUP BY category HAVING COUNT(*) > 10;
HAVING without GROUP BY?
Treats the entire result as one group.
SELECT ? FROM ? WHERE ? GROUP BY ? HAVING ? ORDER BY ? LIMIT.