Difficulty: Beginner → Early Intermediate
Estimated time: 15–20 minutes
SQL concepts: WHERE, GROUP BY, HAVING, COUNT()
Goal: Understand when to filter rows and when to filter groups.
The Challenge
The product manager asks:
“Which categories have at least 2 products that cost more than 50?”
This question looks simple—but it requires a two-step filtering process.
You must:
- Filter individual rows based on price
- Then filter groups of rows based on how many remain
This is where many SQL learners get stuck.
Database Table
products
| column_name | type | description |
|---|---|---|
| product_id | INTEGER | Unique product ID |
| name | TEXT | Product name |
| category | TEXT | Product category |
| price | DECIMAL | Product price |
Sample Data
| product_id | name | category | price |
|---|---|---|---|
| 101 | Wireless Mouse | Accessories | 24.99 |
| 102 | Mechanical Keyboard | Accessories | 89.00 |
| 103 | Webcam | Accessories | 59.99 |
| 104 | Monitor | Displays | 229.99 |
| 105 | USB-C Hub | Accessories | 34.50 |
| 106 | Laptop Stand | Workspace | 39.99 |
Your Task
Write a SQL query that returns:
- Each category
- That has at least 2 products
- Where each counted product costs more than 50
Expected Output
| category |
|---|
| Accessories |
(Mechanical Keyboard + Webcam)
Constraints
- Use
WHEREto filter rows - Use
GROUP BY - Use
HAVINGto filter groups - Use
COUNT() - Do not use
SELECT *
Hint (Optional)
Remember:
WHEREruns before groupingHAVINGruns after grouping
They are not interchangeable.
SELECT
category
FROM products
WHERE price > 50
GROUP BY category
HAVING COUNT(*) >= 2;
Explanation
Let’s break this down step by step:
WHERE price > 50
Filters out products that don’t meet the price requirement.GROUP BY category
Groups the remaining products by category.HAVING COUNT(*) >= 2
Keeps only categories with at least two qualifying products.
This pattern is extremely common in analytics and reporting.
The Key Mental Model (Very Important)
WHERE → filters individual rows
GROUP BY → creates groups
HAVING → filters groups
Once this clicks, a large class of SQL problems becomes much easier.
Common Mistakes
- Using HAVING instead of WHERE
HAVING price > 50❌ Invalid — HAVING works on aggregates, not raw rows. - Filtering after grouping
SQL does not work that way. - Trying to combine everything into one clause
Optional Extension (Mini Bonus)
Try answering these variations:
- Which categories have at least 3 products costing more than 30?
- Which categories have only one expensive product?
- Sort the result alphabetically by category name.
Why this challenge matters
This challenge teaches one of the most important SQL distinctions:
Rows are filtered with
WHERE.
Groups are filtered withHAVING.
If learners understand this, they’re ready for real-world analytics work.
Next Challenge
Beginner Challenge #25: Summing Values with SUM()
🔗 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.