The Ones That Move

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
mid
Asked in
DoorDash

Problem

The merchandising team wants to know which products carry each category by sales, where a product's revenue is its quantity times unit price summed across every order line. For each category return its three strongest products, showing the category, the product name, that revenue, and the product's standing within the category, ordered by category, then standing, then product name.

Every aisle has its champions. Surface the three that carry each one.

Tables

order_items

Columns: item_id INTEGER, order_id INTEGER, product_id INTEGER, user_id INTEGER, quantity INTEGER, unit_price REAL

order_items: 10 of 200 rows
item_idorder_idproduct_iduser_idquantityunit_price
60611038813441167422.3
61221067916872234739.6
618310970203033011056.9
62441126123734368374.2
63051155227165435691.5
636611843305965029108.8
642712134340275692126.1
648812425374586365143.4
654912716408897038160.7
661013007443110701178

products

Columns: product_id INTEGER, product_name TEXT, category TEXT, price REAL, rating REAL, in_stock INTEGER

products: 10 of 200 rows
product_idproduct_namecategorypriceratingin_stock
1001Basic Device 1XBooks17.522.71
1050Deluxe Bundle 2XClothing25.054.41
1099Pro Unit 3XHome & Kitchen32.582.11
1148Ultra Tool 4XCollectibles40.113.81
1197Essential Set 5XToys47.641.51
1246Classic System 6XBeauty03.21
1295Smart Gadget 7XAutomotive62.74.90
1344Eco Kit 8XGarden70.232.61
1393Turbo Pack 9XMusic77.764.30
1442Premium Widget 10XElectronics85.2921

Expected output

First 5 of 32 rows
categoryproduct_namerevenuerevenue_rank
AutomotiveSmart Gadget 97X48941
AutomotiveSmart Gadget 47X35442
AutomotiveSmart Gadget 37X33543
BeautyClassic System 96X57061
BeautyClassic System 86X54782

Worked solution and explanation

Why this problem exists in real interviews

This is a top-N-per-group problem wearing a merchandising costume. The skill being probed: can you rank products inside each category and keep only the leaders, without flattening the categories together or trying to filter a ranking where it cannot be filtered? Anyone can sum revenue and sort it. What separates candidates is knowing that the per-category cutoff has to happen against a computed rank in an outer query, and choosing the ranking function whose tie behavior matches what 'top three' actually means.


Break down the requirements

Step 1: Get revenue to the right grain

Revenue is not a stored column. It is SUM(quantity * unit_price) per product, computed by joining order_items to products and grouping by category and product_name. Multiply first, then sum: SUM(quantity) * SUM(unit_price) is a different, wrong number.

Step 2: Rank within each category, not globally

PARTITION BY category restarts the ranking inside every category, so each aisle gets its own 1, 2, 3. Drop the PARTITION BY and you get a single global leaderboard, which silently answers a different question.

Step 3: Filter the rank in an outer query

You cannot put revenue_rank <= 3 in the same SELECT that defines it; window functions are evaluated after WHERE. Wrap the ranking in a CTE, then filter revenue_rank in the outer query. Keep that rank column in the final SELECT so the output shows each product's standing, and order by category, then standing, then product name so ties resolve the same way every run.


The solution

Top three products per category
WITH product_revenue AS (
  SELECT p.category,
         p.product_name,
         SUM(oi.quantity * oi.unit_price) AS revenue
  FROM order_items oi
  JOIN products p ON p.product_id = oi.product_id
  GROUP BY p.category, p.product_name
),
ranked AS (
  SELECT category,
         product_name,
         revenue,
         DENSE_RANK() OVER (PARTITION BY category ORDER BY revenue DESC) AS revenue_rank
  FROM product_revenue
)
SELECT category, product_name, revenue, revenue_rank
FROM ranked
WHERE revenue_rank <= 3
ORDER BY category, revenue_rank, product_name;

Common follow-up questions