HAVING

Overview

The HAVING clause is used to filter groups after GROUP BY. It's similar to WHERE, but WHERE filters rows before grouping, while HAVING filters groups after aggregation.

HAVING is used with aggregate functions and GROUP BY to filter groups based on aggregate values, which cannot be done with WHERE.

Basic Syntax

HAVING Syntax
SELECT column1, aggregate_function(column2)
FROM table_name
WHERE condition
GROUP BY column1
HAVING aggregate_function(column2) condition;

HAVING vs WHERE

Understanding the difference:

Clause Filters Used With
WHERE Filters rows before grouping Individual rows
HAVING Filters groups after aggregation Grouped rows (aggregates)

SQL Execution Order

Understanding when HAVING is evaluated:

Query Execution Order
1. FROM (identify tables)
2. WHERE (filter rows)
3. GROUP BY (group rows)
4. HAVING (filter groups)
5. SELECT (select columns)
6. ORDER BY (sort results)

Examples

Example 1: Filter Groups by Count

Categories with more than 10 products
SELECT 
    category,
    COUNT(*) AS product_count
FROM Products
GROUP BY category
HAVING COUNT(*) > 10;

Example 2: Filter Groups by Sum

Customers with total orders over $1000
SELECT 
    customer_id,
    SUM(total_amount) AS total_spent
FROM Orders
GROUP BY customer_id
HAVING SUM(total_amount) > 1000;

Example 3: HAVING with WHERE

Combine WHERE and HAVING
SELECT 
    category,
    COUNT(*) AS product_count,
    AVG(price) AS average_price
FROM Products
WHERE price > 50  -- Filter rows before grouping
GROUP BY category
HAVING COUNT(*) > 5  -- Filter groups after grouping
  AND AVG(price) > 100;

Example 4: Multiple HAVING Conditions

Multiple group conditions
SELECT 
    category,
    COUNT(*) AS product_count,
    SUM(stock_quantity) AS total_stock
FROM Products
GROUP BY category
HAVING COUNT(*) > 10
  AND SUM(stock_quantity) > 1000;

Why You Can't Use WHERE for Aggregates

WHERE cannot be used with aggregate functions because WHERE filters rows before aggregation:

Why HAVING is needed
-- ❌ ERROR: Cannot use WHERE with aggregate
SELECT category, COUNT(*)
FROM Products
GROUP BY category
WHERE COUNT(*) > 10;  -- Error!

-- ✅ CORRECT: Use HAVING with aggregate
SELECT category, COUNT(*)
FROM Products
GROUP BY category
HAVING COUNT(*) > 10;  -- Works!

HAVING with Different Aggregates

Example 1: HAVING with AVG

Filter by average
SELECT 
    category,
    AVG(price) AS average_price
FROM Products
GROUP BY category
HAVING AVG(price) > 100;

Example 2: HAVING with MIN and MAX

Filter by min/max
SELECT 
    category,
    MIN(price) AS min_price,
    MAX(price) AS max_price
FROM Products
GROUP BY category
HAVING MAX(price) - MIN(price) > 100;

HAVING with Aliases

Some databases allow using aliases in HAVING, while others require the full expression:

HAVING with alias (varies by database)
-- Using alias in HAVING (works in MySQL)
SELECT 
    category,
    COUNT(*) AS product_count
FROM Products
GROUP BY category
HAVING product_count > 10;

-- Using full expression (works everywhere)
SELECT 
    category,
    COUNT(*) AS product_count
FROM Products
GROUP BY category
HAVING COUNT(*) > 10;

Common Use Cases

Best Practices

Common Mistakes

Next Steps

Learn about checking for existence with EXISTS, or explore conditional logic with CASE.