Unmatched Categories
An easy SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.
- Domain
- SQL
- Difficulty
- easy
- Seniority
- L3
- Asked in
- DoubleVerify
Problem
Find the product categories with three or more items currently out of stock, for the restock list a merchandising analyst pulls from the products table.
Categories with nothing on the shelf. Empty aisles.
Tables
products
Columns: product_id INTEGER, product_name TEXT, category TEXT, price REAL, rating REAL, in_stock INTEGER
| product_id | product_name | category | price | rating | in_stock |
|---|---|---|---|---|---|
| 1001 | Basic Device 1X | Books | 17.52 | 2.7 | 1 |
| 1050 | Deluxe Bundle 2X | Clothing | 25.05 | 4.4 | 1 |
| 1099 | Pro Unit 3X | Home & Kitchen | 32.58 | 2.1 | 1 |
| 1148 | Ultra Tool 4X | Collectibles | 40.11 | 3.8 | 1 |
| 1197 | Essential Set 5X | Toys | 47.64 | 1.5 | 1 |
| 1246 | Classic System 6X | Beauty | 0 | 3.2 | 1 |
| 1295 | Smart Gadget 7X | Automotive | 62.7 | 4.9 | 0 |
| 1344 | Eco Kit 8X | Garden | 70.23 | 2.6 | 1 |
| 1393 | Turbo Pack 9X | Music | 77.76 | 4.3 | 0 |
| 1442 | Premium Widget 10X | Electronics | 85.29 | 2 | 1 |
Expected output
| category |
|---|
| Automotive |
| Books |
| Garden |
| Music |
Worked solution and explanation
This is a threshold on a whole group dressed up as a restock report. Anyone can find sold-out products. What separates candidates is noticing that 'three or more out of stock' describes a category, not a row: you have to count the empty slots per category and only then decide. The reflex SELECT DISTINCT category FROM products WHERE in_stock = 0 answers 'has any sold-out product'. Every category on this catalog does, so it hands back all 11 and the restock list is worthless.
Count, then decide
Step 1: Turn the flag into a sold-out count
in_stock is 1 for buyable and 0 for sold out, so 1 - in_stock is 1 exactly on the empty slots. SUM(1 - in_stock) per category is the number of sold-out products, with no CASE needed.
Step 2: Test the count after grouping
WHERE runs before GROUP BY and only sees one product at a time, so it cannot know a category's total. The condition belongs in HAVING SUM(1 - in_stock) >= 3, which is evaluated once per category.
Step 3: Respect the boundary
Books, Automotive and Garden each have exactly three sold-out products. Write > 3 and all three disappear, leaving only Music with its twenty. 'Three or more' is inclusive.
SELECT category
FROM products
GROUP BY category
HAVING SUM(1 - in_stock) >= 3- Row filter
WHERE in_stock = 0plusDISTINCT categoryasks whether a category has any sold-out product. All 11 do, including Collectibles with a single empty slot, so the list comes back complete and useless.- Group threshold
GROUP BY category HAVING SUM(1 - in_stock) >= 3counts first and decides second. Books, Automotive and Garden reach three, Music reaches twenty, and the other seven stop at one or two.
Common follow-up questions
- What if `in_stock` could be `NULL` for some products? (`1 - NULL` is `NULL` and `SUM` skips it, so unknown stock silently counts as available; decide whether it should.)
- How would you also return each flagged category's sold-out count? (Add `SUM(1 - in_stock)` to the select list under a clear name; the grouping already supports it.)
- What if the bar became a share, such as under 85% in stock? (Tests whether you compare `AVG(in_stock)` instead of integer-dividing two counts.)