Top Product Categories

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
Spark

Problem

A retail marketplace's merchandising team is spotlighting the categories that sell best among its well-reviewed products, where a product's category lives on the products table. Counting only transactions on products rated 3.0 or higher, surface the top three categories by transaction count, and include every category tied at the third spot.

Top three categories by page views.

Tables

transactions

Columns: transaction_id INTEGER, user_id INTEGER, product_id INTEGER, quantity INTEGER, total_amount REAL, transaction_date TEXT

transactions: 10 of 200 rows
transaction_iduser_idproduct_idquantitytotal_amounttransaction_date
10671971001223.462026-02-02
11342941050336.932026-03-03
12013911099450.42026-04-04
12684881148563.872026-05-05
13355851197002026-06-06
14026821246290.812026-07-07
146977912953104.282026-08-08
153687613444117.752026-09-09
160397313935-452026-01-10
1670107014421144.692026-02-11

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 7 rows
categorytxn_countrnk
Clothing111
Beauty111
Garden102
Electronics102
Music83

Worked solution and explanation

What this problem really is

Beneath the merchandising story this is a top-N-with-ties ranking: rank the filtered per-category counts and keep the top three standings, not the top three rows. The trap is reaching for LIMIT 3 or ROW_NUMBER(). Both cut mid-tie: when four categories share the second standing, LIMIT keeps whichever three the engine happens to emit and silently drops a genuine co-leader. DENSE_RANK() is what lets 'include everyone tied at the third spot' actually work. The WHERE p.rating >= 3.0 scope is load-bearing too: drop it and the counts flatten to two tiers and the ranking has nothing to separate.


Break down the requirements

Step 1: Scope to well-reviewed products

Inner-join transactions to products on product_id, and keep only rows where p.rating >= 3.0, so every counted sale sits on a well-reviewed product.

Step 2: Aggregate before you rank

GROUP BY p.category and COUNT(*) for the total transactions in each category.

Step 3: Rank the tiers, not the rows

Assign DENSE_RANK() OVER (ORDER BY COUNT(*) DESC) so tied categories share a standing and the numbering has no gaps, which is what makes 'include all tied at a cutoff' well-defined.

Step 4: Cut at the third standing

Wrap the ranked set and filter WHERE rnk <= 3 in the outer query, keeping the top three distinct standings and every category tied within them.


The solution

TOP CATEGORIES WITH TIES
SELECT category, txn_count, rnk
FROM (
  SELECT
    p.category AS category,
    COUNT(*) AS txn_count,
    DENSE_RANK() OVER (ORDER BY COUNT(*) DESC) AS rnk
  FROM transactions t
  JOIN products p ON t.product_id = p.product_id
  WHERE p.rating >= 3.0
  GROUP BY p.category
) ranked
WHERE rnk <= 3;

COMMON FOLLOW-UP QUESTIONS

Common follow-up questions