Table of Contents
- Introduction
- What is the
HAVINGClause? - Difference Between
WHEREandHAVING - Why Use
HAVING? - Basic Syntax of
HAVING - Simple Example with
HAVING - Using
HAVINGwithCOUNT() - Filtering on
SUM()withHAVING - Using
HAVINGwithAVG(),MIN(),MAX() - Combining
WHEREandHAVING HAVINGwith Multiple Conditions- Sorting After
HAVING HAVINGWithoutGROUP BY(Yes, You Can!)- Real-World Use Case: Active Customers
- Real-World Use Case: Sales by Region
- Common Errors with
HAVING - Performance Considerations
- Best Practices for Using
HAVING - Summary Table:
HAVINGvsWHERE - Summary and What’s Next
1. Introduction
The HAVING clause in SQL allows you to filter grouped data after aggregation. It’s often misunderstood or confused with WHERE, but they serve very different purposes. In this module, we’ll clarify the role of HAVING and teach you how to use it effectively.
2. What is the HAVING Clause?
HAVING is used to filter the results of GROUP BY queries based on aggregate functions like COUNT(), SUM(), AVG(), etc.
3. Difference Between WHERE and HAVING
| Clause | Filters | Applied Before/After Grouping |
|---|---|---|
WHERE | Rows | Before GROUP BY |
HAVING | Groups | After GROUP BY |
4. Why Use HAVING?
HAVING lets you:
- Show only groups that meet certain conditions
- Filter aggregated data
- Extend the power of
GROUP BY
5. Basic Syntax of HAVING
sqlCopyEditSELECT column, AGG_FUNC(column)
FROM table
GROUP BY column
HAVING AGG_FUNC(column) condition;
Example:
sqlCopyEditSELECT department, COUNT(*) AS total_employees
FROM employees
GROUP BY department
HAVING total_employees > 5;
6. Simple Example with HAVING
sqlCopyEditSELECT city, COUNT(*) AS user_count
FROM users
GROUP BY city
HAVING user_count >= 10;
This returns only cities with 10 or more users.
7. Using HAVING with COUNT()
sqlCopyEditSELECT product_id, COUNT(*) AS order_count
FROM orders
GROUP BY product_id
HAVING order_count > 20;
This helps identify popular products.
8. Filtering on SUM() with HAVING
sqlCopyEditSELECT customer_id, SUM(amount) AS total_spent
FROM transactions
GROUP BY customer_id
HAVING total_spent > 1000;
Finds customers who’ve spent over ₹1000.
9. Using HAVING with AVG(), MIN(), MAX()
sqlCopyEditSELECT category, AVG(price) AS avg_price
FROM products
GROUP BY category
HAVING avg_price < 500;
You can apply HAVING to any aggregate metric.
10. Combining WHERE and HAVING
sqlCopyEditSELECT department, COUNT(*) AS total
FROM employees
WHERE is_active = TRUE
GROUP BY department
HAVING total >= 5;
WHEREfilters before groupingHAVINGfilters after aggregation
11. HAVING with Multiple Conditions
sqlCopyEditSELECT region, SUM(sales) AS total_sales
FROM orders
GROUP BY region
HAVING total_sales > 100000 AND COUNT(*) > 10;
You can use AND, OR, and even parentheses for logic.
12. Sorting After HAVING
sqlCopyEditSELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING avg_salary > 40000
ORDER BY avg_salary DESC;
ORDER BY works after HAVING in the execution order.
13. HAVING Without GROUP BY (Yes, You Can!)
Yes, HAVING can be used without GROUP BY — usually to filter on aggregates over the entire table.
sqlCopyEditSELECT SUM(amount) AS total_revenue
FROM sales
HAVING total_revenue > 100000;
14. Real-World Use Case: Active Customers
sqlCopyEditSELECT user_id, COUNT(*) AS login_count
FROM logins
GROUP BY user_id
HAVING login_count >= 20;
Find power users based on login activity.
15. Real-World Use Case: Sales by Region
sqlCopyEditSELECT region, SUM(total_amount) AS total_sales
FROM orders
GROUP BY region
HAVING total_sales > 50000;
Filter out underperforming regions.
16. Common Errors with HAVING
| Mistake | Why it’s Wrong |
|---|---|
Using HAVING without aggregation | Use WHERE instead |
Using WHERE with aggregates | Should be moved to HAVING |
| Forgetting to alias or qualify columns | Leads to confusion or SQL errors |
17. Performance Considerations
- Use
WHEREfor row-level filters to reduce rows before grouping - Avoid putting non-aggregated conditions in
HAVING - Combine
HAVINGwith indexes for faster filtering
18. Best Practices for Using HAVING
- Only use
HAVINGfor aggregated conditions - Use meaningful aliases for readability
- Use
WHEREfirst to limit rows - Document logic when combining with
GROUP BY
19. Summary Table: HAVING vs WHERE
| Feature | WHERE | HAVING |
|---|---|---|
| Filters | Rows | Groups |
| Used With | Any query | With GROUP BY |
| Can Use Aggregates? | ❌ | ✅ |
| Evaluated When? | Before grouping | After grouping |
20. Summary and What’s Next
The HAVING clause is your post-aggregation filter, allowing you to include only those groups that meet a specific condition. Combined with GROUP BY and aggregate functions, it becomes a powerful tool for analytical queries.

