HAVING: Filter Groups
Filter groups after aggregation with HAVING — and understand exactly how it differs from WHERE.
After grouping, you often want only some of the groups: "countries with more than 800 total runs", "teams with more than one player". You cannot use WHERE for this, because the totals don't exist yet when WHERE runs. That is the job of HAVING.
Definition
HAVING filters groups created by GROUP BY. It runs after grouping and aggregation, so its condition can use aggregate functions such as
SUM(runs) > 800. Groups for which the condition is not TRUE are removed from the result.
Syntax
sql
SELECT group_column, AGGREGATE(column) AS alias
FROM table_name
WHERE row_condition -- optional: filters rows BEFORE grouping
GROUP BY group_column
HAVING group_condition; -- filters groups AFTER groupingExample — countries with more than 800 runs
sql
SELECT country, SUM(runs) AS total_runs
FROM players
GROUP BY country
HAVING SUM(runs) > 800;| country | total_runs |
|---|---|
| England | 850 |
| India | 1620 |
Execution order: 1️⃣ FROM → 2️⃣ GROUP BY country (Australia 700, England 850, India 1620) → 3️⃣ HAVING SUM(runs) > 800 removes Australia (700) → 4️⃣ SELECT.
Example — WHERE and HAVING together
sql
SELECT country, SUM(runs) AS total_runs
FROM players
WHERE runs > 100
GROUP BY country
HAVING SUM(runs) > 800;| country | total_runs |
|---|---|
| England | 850 |
| India | 1600 |
How it works — rows first, then groups:
FROM players— 6 rows.WHERE runs > 100— removes Bumrah (20) before grouping → 5 rows.GROUP BY country— India now = 750 + 500 + 350 = 1600 (not 1620!), England 850, Australia 700.HAVING SUM(runs) > 800— removes Australia.SELECT— shows the two remaining groups.
Example — teams with more than one player
sql
SELECT team, COUNT(*) AS players
FROM players
GROUP BY team
HAVING COUNT(*) > 1;| team | players |
|---|---|
| MI | 2 |
WHERE vs HAVING
| WHERE | HAVING | |
|---|---|---|
| Filters | Individual rows | Groups |
| Runs | Before GROUP BY | After GROUP BY |
Can use aggregates (SUM, COUNT)? | ❌ No | ✅ Yes |
| Needs GROUP BY? | No | Normally yes (without it the whole table is one group) |
| Example | WHERE runs > 100 | HAVING SUM(runs) > 800 |
Tip: If a condition does not need an aggregate (e.g.
country = 'India'), put it in WHERE. Removing rows early means less work for GROUP BY — faster queries.
Common mistakes
- ❌
WHERE SUM(runs) > 800→ An aggregate may not appear in the WHERE clause. ✅HAVING SUM(runs) > 800. - ❌
HAVING total_runs > 800(using the SELECT alias) — SQL Server rejects it because HAVING runs before SELECT. ✅ Repeat the expression:HAVING SUM(runs) > 800. - ❌ Putting a plain row filter in HAVING (
HAVING country = 'India'). It may work, but ✅ WHERE is clearer and faster.
Interview tip
Q: Can you use WHERE and HAVING in the same query? In what order are they applied? A: Yes. WHERE is applied first to individual rows, then GROUP BY forms groups, then HAVING filters those groups. So WHERE changes what goes into the totals, while HAVING decides which totals are shown.
Key points to remember
- HAVING filters GROUPS after GROUP BY; WHERE filters ROWS before GROUP BY.
- HAVING can use aggregate functions (SUM, COUNT …); WHERE cannot.
- Execution order: FROM → WHERE → GROUP BY → HAVING → SELECT.
- A WHERE filter changes the totals (rows removed before summing); HAVING only hides whole groups.
- In SQL Server you can't use a SELECT alias in HAVING — repeat the aggregate expression.
- Put non-aggregate conditions in WHERE — filtering early is faster.
Try it yourself
Countries with more than 800 runs
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
WHERE + HAVING together
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Batters with 150+ runs across innings
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Practice: teams with more than one player
Runs on a fresh IPL practice database in your browser · edit the query and press Ctrl + Enter
Revision Flashcards
Tap a card to flip it and see the answer.
