type
status
date
slug
summary
category
tags
password
icon
Medium Tages
Medium Subtitle
WHERE vs HAVING: The SQL Mistake That Breaks Your Queries
You've written what looks like a perfectly reasonable SQL query. You need to find all departments with more than 5 employees. You type
WHERE COUNT(*) > 5, hit enter, and... error.You try again. Same error. You google it. Still confused.
Here's the thing: this is the most common mistake SQL beginners make when learning aggregation. And once you understand the difference between WHERE and HAVING, you'll never make this error again.
In this post, I'll show you exactly when to use each clause, why they're different, and how to fix queries that break because you used the wrong one.
Why Your Query is Breaking
Let's start with the error most beginners hit:
The problem? You cannot use aggregate functions like
COUNT(), SUM(), or AVG() in a WHERE clause.But why not? It seems logical, right? You want to filter results where the count is greater than 5.
Here's what's actually happening behind the scenes. SQL processes your query in a specific order:
- FROM — Gets data from the employees table
- WHERE — Filters individual rows (before any grouping happens)
- GROUP BY — Groups the remaining rows by department
- Aggregate functions — Calculates COUNT(*) for each group
- SELECT — Returns the results
The catch: WHERE runs at step 2, but COUNT(*) doesn't exist until step 4. You're trying to filter based on a calculation that hasn't been performed yet.
Think of it like trying to grade a test before the student has finished taking it. The data you need simply doesn't exist yet at that point in the process.
This is where HAVING comes in.
The Simple Fix: HAVING Clause
The correct version of our query uses HAVING instead:
What's different? HAVING filters after the grouping and aggregation happen, so COUNT(*) already exists when the filter is applied.
Here's the key difference between WHERE and HAVING:
Aspect | WHERE | HAVING |
When it runs | Before GROUP BY | After GROUP BY |
What it filters | Individual rows | Groups of rows |
Can use aggregates | ❌ No | ✅ Yes |
Use case | Filter raw data | Filter aggregated results |
Think of it this way:
- WHERE says: "Show me rows where the employee's salary is over $50,000"
- HAVING says: "Show me departments where the average salary is over $50,000"
WHERE works on individual records before you group them. HAVING works on the grouped summaries after aggregation.
Here's a side-by-side comparison:
In the first query, WHERE removes orders from 2024 and earlier before any grouping happens. In the second query, all orders are grouped by customer first, then HAVING filters out customers whose total is $1000 or less.
When to Use WHERE vs HAVING
Now that you understand the difference, here's how to choose which one to use:
Use WHERE when:
1. Filtering individual rows before aggregation
This removes all employees hired before 2020 from consideration before calculating department averages. It's more efficient because you're working with less data during the grouping phase.
2. Excluding data you don't want to count
Here, cancelled or pending orders never make it into your count. You're filtering the raw data before aggregation.
3. Working with non-aggregated columns
The category column exists in the raw data, so you can filter on it with WHERE.
Use HAVING when:
1. Filtering based on aggregate calculations
You can't know how many orders a customer has until after you've grouped and counted them. This requires HAVING.
2. Finding groups that meet certain thresholds
The total quantity sold is a calculated aggregate, so it only exists after grouping.
3. Comparing aggregates to specific values
💡 Pro Tip: If your condition involvesCOUNT(),SUM(),AVG(),MIN(), orMAX(), you need HAVING, not WHERE.
Using Both WHERE and HAVING Together
Here's where it gets powerful: you can use both in the same query.
WHERE filters the data going into the groups. HAVING filters the groups coming out.
What's happening here:
- WHERE filters out employees hired before 2020
- Remaining employees are grouped by department
- Average salary and count are calculated for each department
- HAVING filters out departments that don't meet both conditions (avg salary > 60K AND 3+ employees)
The result? You get only departments with recent hires, where those recent hires earn good money, and where there are at least 3 of them.
Real-World Example
Let's say you're analyzing customer behavior for an e-commerce site. You want to find your best customers from this year:
This query finds customers who:
- Made purchases in 2025 (WHERE)
- Have completed orders only, no cancelled ones (WHERE)
- Placed at least 3 orders (HAVING)
- Spent over $500 total (HAVING)
WHERE handles the date and status filters because those exist on individual orders. HAVING handles the count and total spent because those only exist after grouping and aggregating.
You couldn't write this query with WHERE alone or HAVING alone. You need both.
Common Mistakes to Avoid
Even after understanding the difference, here are traps beginners fall into:
Mistake 1: Using WHERE for aggregates
If you see an error like "aggregate functions are not allowed in WHERE," this is your problem. Move the condition to HAVING.
Mistake 2: Using HAVING without GROUP BY
HAVING without GROUP BY treats the entire result set as one group. It's technically valid but rarely what you want. If you're not grouping, you probably don't need HAVING.
Mistake 3: Forgetting to repeat the aggregate in HAVING
While some databases (like PostgreSQL and MySQL) let you reference the column alias in HAVING, not all do. For maximum compatibility, repeat the aggregate function.
Conclusion
The WHERE vs HAVING confusion trips up every SQL beginner. But now you know the secret: WHERE filters rows before grouping, HAVING filters groups after aggregation.
Quick reference:
Use WHERE to:
- Filter individual rows
- Exclude data before grouping
- Work with non-aggregated columns
- Improve query performance (filtering early is faster)
Use HAVING to:
- Filter based on aggregate functions (COUNT, SUM, AVG, etc.)
- Find groups meeting specific thresholds
- Work with grouped results
Use both together to:
- Filter input data (WHERE) and output groups (HAVING)
- Create sophisticated analytics queries
- Combine row-level and aggregate-level filtering
The simple rule: If your filter condition uses an aggregate function like COUNT(), SUM(), or AVG(), use HAVING. If it uses regular columns, use WHERE.
Next time you see an error about aggregate functions in WHERE, you'll know exactly what to do: move that condition to HAVING.
Want to practice? Try these challenges:
- Find customers with more than 5 orders
- Calculate departments with average salary above company average
- Identify products sold in quantities over 1,000 units
- Find categories with at least 10 products and average price under $100
Understanding WHERE vs HAVING is fundamental to writing effective SQL queries. Master this difference, and you'll write cleaner, error-free queries every time.
上一篇
Build Your First Sales Dashboard: SQL Aggregation for Beginners
下一篇
5 SQL GROUP BY Mistakes That Make You Look Like a Beginner (And How to Fix Them)
Loading...


.jpg?table=block&id=29b4acfb-1cac-80cb-97e9-d6504a23ba23&t=29b4acfb-1cac-80cb-97e9-d6504a23ba23)

