Ranking Customers by Typical Order Size
Whetcode Supply is rebuilding its VIP programme. The old version picked a single "top customer" by total spend, and it kept crowning the same person for placing a lot of small orders. What the team wants this time is a full board built on typical basket size — how big a customer's average order is, rather than how many they placed.
Two things stand between you and that number. An order row records units bought but not their price, which lives on the product. And one customer's average will not divide evenly, so the answer carries a repeating decimal.
orders — one row per order. quantity is units bought. product_id points at a row in products.
| id | customer_id | product_id | quantity | order_date |
|---|---|---|---|---|
| 1 | 1 | 1 | 2 | 2023-02-01 |
| 2 | 1 | 4 | 1 | 2023-02-01 |
| 3 | 2 | 2 | 1 | 2023-02-10 |
| 4 | 3 | 3 | 3 | 2023-03-05 |
| 5 | 4 | 5 | 5 | 2023-03-11 |
| 6 | 1 | 3 | 1 | 2023-04-02 |
| 7 | 5 | 1 | 4 | 2023-05-20 |
| 8 | 2 | 5 | 2 | 2023-05-22 |
| 9 | 3 | 4 | 1 | 2023-06-01 |
| 10 | 5 | 2 | 1 | 2023-06-15 |
products — one row per product. price is the price of a single unit, in dollars.
| id | name | category | price |
|---|---|---|---|
| 1 | Wireless Mouse | electronics | 25.0 |
| 2 | Standing Desk | furniture | 350.0 |
| 3 | Desk Lamp | furniture | 40.0 |
| 4 | Mechanical Keyboard | electronics | 85.0 |
| 5 | Notebook Set | office | 12.0 |
Both tables already exist in the database — there is nothing to create or load.
Task: Write a query returning three columns, customer_id, avg_order_value and value_rank, with one row per customer who has placed at least one order. avg_order_value is the mean value of that customer's orders. An order's value is its quantity multiplied by the unit price of the product ordered. It is not rounded — one customer's figure prints as a long repeating decimal, and that is the expected answer. value_rank is their position on the board, 1 for the largest average. Two customers on exactly equal averages share a position and the position after it is skipped. Rows come back sorted by value_rank, best position first, and two customers sharing a position by customer_id.
Example output — shape only, on invented customers. Nothing is rounded, so an average that does not divide cleanly prints its full repeating tail, and the two customers level on it share a position.
| customer_id | avg_order_value | value_rank |
|---|---|---|
| 6 | 240 | 1 |
| 8 | 91.66666666666667 | 2 |
| 9 | 91.66666666666667 | 2 |
| 7 | 45.5 | 4 |
Sign in to solve this problem
Reading problems is free for everyone — solving them (Run, Submit, and tracking what you've solved) needs an account.
Sign in