Your Page Title
🔍

    SQL GROUP BY, HAVING

    When working with databases, we often need to group data and apply calculations like totals, averages, or counts. In SQL, this is done using the GROUP BY clause. Sometimes, after grouping, we want to filter the grouped results — that’s where HAVING comes in.

    Let’s break this down step-by-step.


    1. What is GROUP BY in SQL?

    The GROUP BY clause groups rows that have the same values in specified columns into summary rows. It is usually used with aggregate functions like:

    • COUNT() – counts the number of rows
    • SUM() – adds values
    • AVG() – calculates the average
    • MAX() – finds the highest value
    • MIN() – finds the lowest value

    Syntax:

    SELECT column_name, aggregate_function(column_name)
    FROM table_name
    GROUP BY column_name;

    Key Points:

    • It groups rows based on one or more columns.
    • It is always used after the WHERE clause and before ORDER BY.
    • It works with aggregate functions to produce summarized results.

    Example:

    Suppose we have a table Orders:

    OrderIDCustomerAmount
    1John250
    2Emma300
    3John150
    4Emma200
    5Alex500

    Query:

    SELECT Customer, SUM(Amount) AS TotalAmount
    FROM Orders
    GROUP BY Customer;

    Result:

    CustomerTotalAmount
    John400
    Emma500
    Alex500

    Here:

    • We grouped the data by Customer.
    • SUM(Amount) added up the orders for each customer.

    2. What is HAVING in SQL?

    The HAVING clause filters the results of groups created by GROUP BY.
    While WHERE filters rows before grouping, HAVING filters after grouping.

    Syntax:

    SELECT column_name, aggregate_function(column_name)
    FROM table_name
    GROUP BY column_name
    HAVING condition;

    Key Points:

    • You cannot use aggregate functions directly with WHERE.
    • Use HAVING to filter grouped results based on aggregate values.

    Example:

    Continuing with the same Orders table.

    Query:

    SELECT Customer, SUM(Amount) AS TotalAmount
    FROM Orders
    GROUP BY Customer
    HAVING SUM(Amount) > 400;

    Result:

    CustomerTotalAmount
    Emma500
    Alex500

    Here:

    • We grouped the data by Customer.
    • Then used HAVING to show only customers whose total amount is more than 400.

    3. Difference Between WHERE and HAVING

    FeatureWHEREHAVING
    Filters rows before grouping
    Filters groups after grouping
    Can use aggregate functions
    Used with GROUP BYOptionalYes, usually

    Example:

     Filter before grouping
    SELECT Customer, SUM(Amount)
    FROM Orders
    WHERE Amount > 200
    GROUP BY Customer;

    -- Filter after grouping
    SELECT Customer, SUM(Amount)
    FROM Orders
    GROUP BY Customer
    HAVING SUM(Amount) > 400;

    4. Using Multiple Columns with GROUP BY

    You can group by more than one column.

    Example:

    SELECT Customer, OrderID, SUM(Amount)
    FROM Orders
    GROUP BY Customer, OrderID;

    This groups rows by Customer and OrderID together.


    5. Practical Example: Sales Report

    Let’s say you have a Sales table:

    ProductRegionSales
    PhoneEast200
    PhoneWest150
    LaptopEast300
    LaptopWest250
    PhoneEast100

    Query to find total sales per product per region where sales exceed 250:

    SELECT Product, Region, SUM(Sales) AS TotalSales
    FROM Sales
    GROUP BY Product, Region
    HAVING SUM(Sales) > 250;

    Result:

    ProductRegionTotalSales
    LaptopEast300

    6. Summary

    • GROUP BY → Groups rows based on column values.
    • HAVING → Filters grouped results (works with aggregates).
    • WHERE filters before grouping, HAVING filters after grouping.
    • Often used together to create powerful summaries in SQL.

    Example Putting It All Together:

    SELECT Customer, COUNT(OrderID) AS OrdersCount, SUM(Amount) AS TotalAmount
    FROM Orders
    WHERE Amount > 100
    GROUP BY Customer
    HAVING SUM(Amount) > 300
    ORDER BY TotalAmount DESC;

    This query:

    1. Filters orders above 100 (WHERE).
    2. Groups by customer (GROUP BY).
    3. Keeps only customers with total purchases over 300 (HAVING).
    4. Sorts results in descending order.

    Final Tip:
    Think of GROUP BY as creating “buckets” of similar data, and HAVING as a filter that decides which buckets to keep.