The partnerships team wants to feature restaurants that have enough order volume and a strong average rating. Some customers skip the rating prompt, so rating can be NULL.
From restaurant_orders, return restaurant_name, total_orders, rated_orders (orders that have a rating) and avg_rating (rounded to 2 decimals) for restaurants with at least 3 orders and an average rating of 4.2 or higher. Order by avg_rating descending, then restaurant_name.
Sample data
Table: restaurant_orders
18 row(s) · showing first 8
| order_idINT | restaurant_nameTEXT | cityTEXT | order_valueNUMERIC(8,2) | ratingINT |
|---|---|---|---|---|
| 1 | Spice Route | Delhi | 640.00 | 5 |
| 2 | Spice Route | Delhi | 820.00 | 4 |
| 3 | Spice Route | Delhi | 560.00 | 5 |
| 4 | Spice Route | Delhi | 710.00 | NULL |
| 5 | Dosa Junction | Bengaluru | 280.00 | 4 |
| 6 | Dosa Junction | Bengaluru | 310.00 | 4 |
| 7 | Dosa Junction | Bengaluru | 350.00 | 5 |
| 8 | Dosa Junction | Bengaluru | 260.00 | 4 |
restaurant_orders
- order_idINT
- restaurant_nameTEXT
- cityTEXT
- order_valueNUMERIC(8,2)
- ratingINT
- Step 1: Conditions on aggregates such as `COUNT(*)` and `AVG(rating)` cannot go in `WHERE`; they belong in `HAVING`, which runs after grouping.
- Step 2: `COUNT(*)` counts every order, while `COUNT(rating)` skips NULLs, which gives the number of rated orders.
- Step 3: `AVG(rating)` also ignores NULLs, so Spice Route averages (5 + 4 + 5) / 3, not / 4.
- Step 4: Tandoor Tales has a perfect average but only 2 orders, so the volume condition removes it.
SELECT restaurant_name,
COUNT(*) AS total_orders,
COUNT(rating) AS rated_orders,
ROUND(AVG(rating), 2) AS avg_rating
FROM restaurant_orders
GROUP BY restaurant_name
HAVING COUNT(*) >= 3
AND AVG(rating) >= 4.2
ORDER BY avg_rating DESC, restaurant_name;More HAVING questions
Practising alone only goes so far — our live cohorts pair SQL depth with dashboards, agentic analytics projects and mock interviews.
Explore the program