Skip to content
Laviyx Learn

Try

SQL GROUP BY and HAVING Practice

Group sales data by one or more columns, combine WHERE with HAVING, and filter groups by their totals, averages and counts.

Intermediate7 problemsUpdated

Review first: GROUP BY, HAVING, Aggregate Functions

All problems use this sales table:

sale_idrepregionproductunitsamount
1AshaNorthLaptop2110000
2RaviSouthPhone575000
3AshaNorthPhone345000
4MeeraEastLaptop155000
5RaviSouthLaptop155000
6KiranNorthTablet460000
7MeeraEastPhone230000
8AshaNorthTablet115000
9KiranNorthPhone690000
10RaviSouthTablet230000
Try your answers on these tables in the SQL Playground
  1. 1.Revenue by region

    Intermediate

    For each region, return the total amount as revenue and the number of sales as sales. Show the highest revenue first.

    Show hint

    GROUP BY region, with SUM and COUNT in the SELECT.

    Show solution
    SQLRun
    SELECT region,
           SUM(amount) AS revenue,
           COUNT(*)    AS sales
    FROM sales
    GROUP BY region
    ORDER BY revenue DESC;
    Output
    region | revenue | sales
    -------+---------+------
    North  | 320000  | 5
    South  | 160000  | 3
    East   | 85000   | 2
  2. 2.Group by two columns

    Intermediate

    Return the total units sold for every combination of region and product as units, sorted by region and then product.

    Show hint

    List both columns in GROUP BY. Each unique pair becomes one group.

    Show solution
    SQLRun
    SELECT region, product, SUM(units) AS units
    FROM sales
    GROUP BY region, product
    ORDER BY region, product;
    Output
    region | product | units
    -------+---------+------
    East   | Laptop  | 1
    East   | Phone   | 2
    North  | Laptop  | 2
    North  | Phone   | 9
    North  | Tablet  | 5
    South  | Laptop  | 1
    South  | Phone   | 5
    South  | Tablet  | 2
  3. 3.Reps above a target

    Intermediate

    Return each rep whose total sales amount is more than 150000, with that total as total. Highest total first.

    Show hint

    You cannot use SUM() in WHERE. Filter groups with HAVING.

    Show solution
    SQLRun
    SELECT rep, SUM(amount) AS total
    FROM sales
    GROUP BY rep
    HAVING SUM(amount) > 150000
    ORDER BY total DESC;
    Output
    rep  | total
    -----+-------
    Asha | 170000
    Ravi | 160000

    Kiran's total is exactly 150000, so "more than 150000" (>) excludes Kiran. Read limits in a question carefully; >= would include Kiran.

  4. 4.WHERE and HAVING together

    Intermediate

    Considering Phone sales only, return each rep who sold at least 5 phone units in total, with the units as phone_units. Most units first.

    Show hint

    WHERE keeps only Phone rows before grouping; HAVING then filters the groups.

    Show solution
    SQLRun
    SELECT rep, SUM(units) AS phone_units
    FROM sales
    WHERE product = 'Phone'
    GROUP BY rep
    HAVING SUM(units) >= 5
    ORDER BY phone_units DESC;
    Output
    rep   | phone_units
    ------+------------
    Kiran | 6
    Ravi  | 5

    Filtering product = 'Phone' in WHERE is correct and efficient, because it is a condition on individual rows. Only conditions on aggregates (like SUM(units)) belong in HAVING.

  5. 5.Average sale above 50000

    Intermediate

    Return each product whose average sale amount is above 50000, with the average rounded to 2 decimals as avg_amount.

    Show hint

    HAVING AVG(amount) > 50000.

    Show solution
    SQLRun
    SELECT product, ROUND(AVG(amount), 2) AS avg_amount
    FROM sales
    GROUP BY product
    HAVING AVG(amount) > 50000
    ORDER BY avg_amount DESC;
    Output
    product | avg_amount
    --------+-----------
    Laptop  | 73333.33
    Phone   | 60000

    The Laptop average is (110000 + 55000 + 55000) / 3 = 73333.33 and the Phone average is exactly 60000. The Tablet average is 35000, so it is filtered out.

  6. 6.Reps who sold every product

    Intermediate

    There are three products. Return the reps who sold all three of them.

    Show hint

    Count the distinct products per rep and keep the reps where that count is 3.

    Show solution
    SQLRun
    SELECT rep
    FROM sales
    GROUP BY rep
    HAVING COUNT(DISTINCT product) = 3
    ORDER BY rep;
    Output
    rep
    ----
    Asha
    Ravi

    To avoid hard-coding the 3, compare with a subquery instead, HAVING COUNT(DISTINCT product) = (SELECT COUNT(DISTINCT product) FROM sales). The query keeps working when a fourth product is added.

  7. 7.Biggest and smallest sale per region

    Intermediate

    For each region, return the biggest sale as biggest, the smallest as smallest, and the difference between them as spread. Sort by region.

    Show hint

    You can do arithmetic with aggregate results, for example MAX(amount) - MIN(amount).

    Show solution
    SQLRun
    SELECT region,
           MAX(amount) AS biggest,
           MIN(amount) AS smallest,
           MAX(amount) - MIN(amount) AS spread
    FROM sales
    GROUP BY region
    ORDER BY region;
    Output
    region | biggest | smallest | spread
    -------+---------+----------+-------
    East   | 55000   | 30000    | 25000
    North  | 110000  | 15000    | 95000
    South  | 75000   | 30000    | 45000