The Heavy Lifters
A medium SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.
- Domain
- SQL
- Difficulty
- medium
- Seniority
- L4
- Asked in
- Burtch Works
Problem
Return the product categories where orders of $1,000 or more bring in more than half of the category's total revenue, listed alphabetically. We count an order's revenue as its total_amount in transactions and take its category from the ordered product in products.
In some categories, a handful of big orders carry the rest.
Tables
transactions
Columns: transaction_id INTEGER, user_id INTEGER, product_id INTEGER, quantity INTEGER, total_amount REAL, transaction_date TEXT
| transaction_id | user_id | product_id | quantity | total_amount | transaction_date |
|---|---|---|---|---|---|
| 1067 | 197 | 1001 | 2 | 23.46 | 2026-02-02 |
| 1134 | 294 | 1050 | 3 | 36.93 | 2026-03-03 |
| 1201 | 391 | 1099 | 4 | 50.4 | 2026-04-04 |
| 1268 | 488 | 1148 | 5 | 63.87 | 2026-05-05 |
| 1335 | 585 | 1197 | 0 | 0 | 2026-06-06 |
| 1402 | 682 | 1246 | 2 | 90.81 | 2026-07-07 |
| 1469 | 779 | 1295 | 3 | 104.28 | 2026-08-08 |
| 1536 | 876 | 1344 | 4 | 117.75 | 2026-09-09 |
| 1603 | 973 | 1393 | 5 | -45 | 2026-01-10 |
| 1670 | 1070 | 1442 | 1 | 144.69 | 2026-02-11 |
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 |
|---|
| Beauty |
| Sports |
| Toys |
Worked solution and explanation
What this problem is really testing
Remove the merchandising story and this is a per-group share test. Inside each category, does the revenue from orders of $1,000 or more beat half of everything the category sold? The skill is computing a conditional numerator and the full denominator over the same group in one pass. Finding the four-figure orders is the easy part. The trap is finding them with a WHERE before the GROUP BY. That removes the smaller orders, so every group's share becomes 100 percent, and on this data you return ten categories when only three qualify.
Build it up
Step 1: Attach a category to each order
Inner-join transactions to products on product_id. Some transactions carry a NULL product_id. They have no category, and the inner join is what keeps them out of the answer.
Step 2: Group by category
GROUP BY p.category gives one row per category. Both sums must be computed over that same set of rows, and that set includes the refund and the voided sale.
Step 3: Compare big-order revenue to half the total
In HAVING, require the conditional sum to be strictly greater than 0.5 * SUM(t.total_amount). Use total_amount as stored, because it is already the order's full value; never multiply it by quantity.
The solution
SELECT p.category
FROM transactions t
JOIN products p ON t.product_id = p.product_id
GROUP BY p.category
HAVING SUM(CASE WHEN t.total_amount >= 1000 THEN t.total_amount ELSE 0 END) > 0.5 * SUM(t.total_amount)
ORDER BY p.categorySELECT p.category
FROM transactions t
JOIN products p ON t.product_id = p.product_id
WHERE t.total_amount >= 1000
GROUP BY p.category
ORDER BY p.categoryWrong: this returns every category with a single four-figure order, ten rows instead of three.
- Filter first, then group
WHERE t.total_amount >= 1000throws out the smaller orders before grouping, so each group holds only big-order revenue. Every category except 'Collectibles' has at least one such order, so ten categories come back.- Conditional sum over the whole group
- The
CASEinsideSUMcounts the small orders as zero without removing them, soSUM(t.total_amount)still sees the whole category. Only 'Beauty', 'Sports' and 'Toys' clear half.
Common follow-up questions
- How would you also report each category's big-order share as a percentage? (Moves both sums into the `SELECT` list next to a computed ratio.)
- What if the cutoff should be the top 10 percent of orders by `total_amount` instead of a fixed $1,000? (Tests deriving the threshold from the data, for example with a percentile in a CTE.)
- How does your query behave if `total_amount` can be `NULL`? (Tests how `CASE` and `SUM` treat missing values in the numerator and the denominator.)