Skip to main content

HAVING

Learning Focus

Use this lesson to understand HAVING — filtering group results that WHERE cannot touch.

HAVING vs WHERE​

ClauseFiltersRuns
WHEREIndividual rowsBefore GROUP BY
HAVINGAggregated groupsAfter GROUP BY

Basic Syntax​

SELECT column, aggregate_function(col)
FROM table
GROUP BY column
HAVING aggregate_function(col) condition;

Examples​

Example 1: Departments with More Than 1 Employee​

SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department
HAVING COUNT(*) > 1;

Example 2: Departments with Average Salary Above Threshold​

SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 75000
ORDER BY avg_salary DESC;

Example 3: Combine WHERE and HAVING​

-- Only active employees, departments with > 1 person
SELECT department, COUNT(*) AS count
FROM employees
WHERE active = true
GROUP BY department
HAVING COUNT(*) > 1;

Example 4: HAVING with Multiple Conditions​

SELECT department, MIN(salary) AS min_sal, MAX(salary) AS max_sal
FROM employees
GROUP BY department
HAVING MIN(salary) > 60000 AND MAX(salary) < 100000;

Common Pitfalls​

PitfallConsequencePrevention
Using WHERE for aggregate conditionsError or logic bugUse HAVING for any condition on an aggregate
HAVING without GROUP BYReturns entire table as one groupAlways pair HAVING with GROUP BY
Referencing SELECT alias in HAVINGMay not work in all DBsDuckDB supports alias reference in HAVING

Quick Reference​

GROUP BY col HAVING COUNT(*) > 5
GROUP BY col HAVING AVG(salary) > 80000
GROUP BY col HAVING SUM(amount) BETWEEN 1000 AND 5000

What's Next​