SQL Beginner Challenge 7: Filter Groups with HAVING

Difficulty: Beginner
Estimated time: 10–15 minutes
SQL concepts: GROUP BY, HAVING, filtering aggregated results
Goal: Learn the difference between filtering rows (WHERE) and filtering groups (HAVING).

The Scenario

After your “products per category” report, the product manager asks a follow-up:

“Show me only the categories that have at least 2 products.”

You already know how to count products per category using GROUP BY.
Now you need to filter the grouped results based on the count.

That’s exactly what HAVING is for.

Database Table

products

column_nametypedescription
product_idINTEGERUnique product ID
nameTEXTProduct name
categoryTEXTProduct category
priceDECIMALProduct price
stock_qtyINTEGERUnits in stock
created_atTIMESTAMPWhen the product was created

Sample Data (for context)

product_idnamecategoryprice
101Wireless MouseAccessories24.99
102Mechanical KeyboardAccessories89.00
10327-inch MonitorDisplays229.99
104USB-C HubAccessories34.50
105Laptop StandWorkspace39.99

Your Task

Write a SQL query that returns:

  • category
  • total_products

…but only for categories where the number of products is 2 or more.

Expected Output

categorytotal_products
Accessories3

(With the sample data, only Accessories has 2+ products.)

Constraints

  • Use GROUP BY
  • Use COUNT() to calculate totals
  • Filter groups using HAVING
  • Do not use WHERE to filter the grouped totals

Hint (Optional)

  • WHERE filters rows before grouping
  • HAVING filters groups after grouping

If you need to filter on an aggregate like COUNT(*), you almost always need HAVING.

SELECT
category,
COUNT() AS total_products FROM products GROUP BY category HAVING COUNT() >= 2;

Explanation

  • GROUP BY category forms one group per category.
  • COUNT(*) counts how many rows are in each group.
  • HAVING COUNT(*) >= 2 keeps only the groups that meet the requirement.

Common Mistakes

  1. Using WHERE with an aggregate
    WHERE COUNT(*) >= 2 -- ❌ not valid
  2. Placing HAVING before GROUP BY
  3. Confusing WHERE and HAVING
    • WHERE filters raw rows
    • HAVING filters aggregated groups

Optional Extension (Mini Bonus)

Try:

  1. Show categories where the average price is above 50.
  2. Show categories with at least 2 products, then sort by total_products descending.
  3. Combine WHERE + GROUP BY + HAVING:
    • Count products per category only for products priced above 20
    • Then show only categories with at least 2 products

Next Challenge

Beginner Challenge #8: Join Two Tables with INNER JOIN

🔗 View reference solution on GitHub
(After you’ve tried the challenge)

Want more practical SQL challenges?
Subscribe to the Solve With SQL newsletter and get new problems delivered to your inbox.