Category Sales Summary

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
Workday

Problem

A merchandising team is sizing up how each product category performs, looking only at items currently in stock. For every category with a sale, show how many different products it sold and the total revenue they brought in, highest revenue first.

Category by category. How did they do?

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 10 rows
categoryproducts_soldtotal_revenue
Electronics913111.02
Automotive811666.7
Books79444.15
Sports69387.24
Collectibles1127.74

Worked solution and explanation

What this really is

This is a distinct-product count wearing a sales-report costume. The skill being probed: can you count PRODUCTS, not sales, per category while summing money in the same pass and keeping discontinued lines out? Anyone can join transactions to products and group by category. The trap is the product figure: a popular product gets bought over and over, so a plain COUNT of the joined rows counts that product once per receipt. Reach for COUNT(*) and your 'products' number is really a sales number, and the categories carrying a few hot repeat-sellers balloon up the leaderboard for no real reason. Miss the in-stock filter and you also fold discontinued items' revenue back into the totals.


Working it out

Step 1: Join, then drop out-of-stock lines

Join transactions to products on product_id so every sale carries its category, then keep only in-stock items with p.in_stock = 1. That filter matters more than it looks: out-of-stock products still have historical transactions, so with no filter you quietly add discontinued lines back into both the product count and the revenue.

Step 2: Dedup the products, total the money

Group by p.category. Use COUNT(DISTINCT t.product_id) for products so a hot seller bought many times still counts as one product, and SUM(t.total_amount) for revenue so you total the amount actually charged rather than recomputing price times quantity.

Step 3: Sort by revenue, let the join filter

ORDER BY total_revenue DESC floats the strongest categories to the top, which is the only order the ask names. There is no HAVING to write: an inner join means a category with no sale never appears, which is exactly the 'made a sale' rule.


The solution

Per-category products and revenue
SELECT
    p.category,
    COUNT(DISTINCT t.product_id) AS products_sold,
    SUM(t.total_amount) AS total_revenue
FROM transactions t
JOIN products p ON t.product_id = p.product_id
WHERE p.in_stock = 1
GROUP BY p.category
ORDER BY total_revenue DESC

Common follow-up questions