- This topic is empty.
-
AuthorPosts
-
February 19, 2026 at 8:24 am #6109
✅ Introduction
When learning SQL, many beginners try to filter grouped data using the
WHEREclause and get confused when it doesn’t work.For example, while working with school data, you may want to find cities that have 3 or fewer public schools.
You might write a query like this:
SELECT city, COUNT(*) AS cc FROM schools WHERE type = "Public School" AND cc <= 3 GROUP BY city ORDER BY cc DESC, city ASC;But when you run it, SQL throws an error.
Why?
Because
WHEREandCOUNT()do not work together the way many people expect.In this tutorial, we’ll understand:
- Why this query fails
- What
HAVINGis - When to use
WHEREvsHAVING - How to write the correct solution
📌 Initial Context
Suppose you are analyzing education data and want to answer this question:
Which cities in Massachusetts have 3 or fewer public schools?
To solve this, you need to:
- Select only public schools
- Group them by city
- Count schools per city
- Keep only cities with 3 or fewer schools
- Sort the results
This requires aggregation — and that’s where
HAVINGcomes in.
❌ The Common Mistake
Many learners try this first:
SELECT city, COUNT(*) AS cc FROM schools WHERE type = "Public School" AND cc <= 3 GROUP BY city ORDER BY cc DESC, city ASC;This looks logical, but it is wrong.
Let’s see why.
⚠️ Why This Query Fails
1️⃣
ccDoes Not Exist in WHEREThe alias
ccis created here:COUNT(*) AS ccBut
WHEREruns beforeSELECT.So when SQL reads:
AND cc <= 3It says:
“I don’t know what
ccis yet.”Because
cchasn’t been calculated.
2️⃣ WHERE Cannot Filter Aggregates
COUNT(*)is an aggregate function.WHEREworks on individual rows, not on grouped results.So you cannot filter counts using
WHERE.
🧠 How SQL Executes This Query
SQL follows this logical order:
1️⃣ FROM 2️⃣ WHERE 3️⃣ GROUP BY 4️⃣ COUNT() 5️⃣ HAVING 6️⃣ SELECT 7️⃣ ORDER BYImportant point:
👉
HAVINGruns afterCOUNT()
👉WHEREruns beforeCOUNT()That’s why
HAVINGis needed.
✅ The Correct Solution: Using HAVING
To filter grouped results, use
HAVING:SELECT city, COUNT(*) AS cc FROM schools WHERE type = 'Public School' GROUP BY city HAVING cc <= 3 ORDER BY cc DESC, city ASC;Now the query works correctly.
🔍 Why This Works
Step by step:
1️⃣
FROM schools→ load data
2️⃣WHERE type = 'Public School'→ keep only public schools
3️⃣GROUP BY city→ group by city
4️⃣COUNT(*)→ count schools in each city
5️⃣HAVING cc <= 3→ keep small groups
6️⃣SELECT→ display results
7️⃣ORDER BY→ sort outputSo
HAVINGfilters after counting.
📌 Alternative (Safer Version)
Some SQL engines prefer this version:
SELECT city, COUNT(*) AS cc FROM schools WHERE type = 'Public School' GROUP BY city HAVING COUNT(*) <= 3 ORDER BY cc DESC, city ASC;This avoids using the alias in
HAVING.Both versions are correct.
🆚 WHERE vs HAVING (Comparison Table)
Feature WHERE HAVING Filters Rows Groups Runs Before GROUP BY After GROUP BY Works with COUNT ❌ No ✅ Yes Used for Normal conditions Aggregates
🧠 Easy Memory Trick
Remember this:
WHERE filters rows. HAVING filters groups.
⭐ Real-World Meaning
In this example:
WHEREremoves non-public schoolsGROUP BYgroups by cityCOUNTcounts schoolsHAVINGremoves big citiesORDER BYsorts results
So you are saying:
“Show me cities that have only a few public schools.”
🏁 Key Takeaways
✔
WHEREcannot use COUNT
✔ Aliases are not available in WHERE
✔ UseHAVINGfor aggregates
✔GROUP BYmust come before HAVING
✔ This is essential for reporting queries
📘 Final Answer (Recommended)
SELECT city, COUNT(*) AS cc FROM schools WHERE type = 'Public School' GROUP BY city HAVING COUNT(*) <= 3 ORDER BY cc DESC, city ASC;
🚀 One-Line Summary
Use
WHEREto filter rows.
UseHAVINGto filter counts.
-
AuthorPosts
- You must be logged in to reply to this topic.

