Question
What is the total items and amount spent for each member before they became a member?
Solution
WITH orders_by_customer_before_membership AS (
SELECT sales.customer_id, order_date, product_id
FROM sales
INNER JOIN members m ON sales.customer_id = m.customer_id
WHERE order_date < m.join_date
)
SELECT orders_by_customer_before_membership.customer_id,
SUM(price),
COUNT(*)
FROM orders_by_customer_before_membership
INNER JOIN menu ON menu.product_id = orders_by_customer_before_membership.product_id
GROUP BY customer_id;
| customer_id | sum | count |
|---|---|---|
| B | 40 | 3 |
| A | 25 | 2 |
Note: Since Customer C never became a member, we won’t include them in this calculation. But if we were asked to, we’d have to change the orders_by_customer_before_membership table to the following:
SELECT sales.customer_id, order_date, product_id
FROM sales
- INNER JOIN members m ON sales.customer_id = m.customer_id
+ LEFT OUTER JOIN members m ON sales.customer_id = m.customer_id
- WHERE order_date < m.join_date
+ WHERE order_date < m.join_date OR m.join_date IS NULL
This would produce the following as the final result:
| customer_id | sum | count |
|---|---|---|
| B | 40 | 3 |
| C | 36 | 3 |
| A | 25 | 2 |
Walkthrough
Let’s start by building an intermediate table of all the sales records for customer before they became a member.
SELECT sales.customer_id, order_date, product_id, m.join_date
FROM sales
INNER JOIN members m ON sales.customer_id = m.customer_id
WHERE order_date < m.join_date;
| customer_id | order_date | product_id | join_date |
|---|---|---|---|
| A | 2021-01-01 | 1 | 2021-01-07 |
| A | 2021-01-01 | 2 | 2021-01-07 |
| B | 2021-01-01 | 2 | 2021-01-09 |
| B | 2021-01-02 | 2 | 2021-01-09 |
| B | 2021-01-04 | 1 | 2021-01-09 |
Now, the total number of items they purchased is the number of sales (i.e. COUNT of the rows), and the total amount they spent is the SUM of the prices of the items in the sales records.
WITH orders_by_customer_before_membership AS (
SELECT sales.customer_id, order_date, product_id
FROM sales
INNER JOIN members m ON sales.customer_id = m.customer_id
WHERE order_date < m.join_date
)
SELECT orders_by_customer_before_membership.customer_id,
SUM(price),
COUNT(*)
FROM orders_by_customer_before_membership
INNER JOIN menu ON menu.product_id = orders_by_customer_before_membership.product_id
GROUP BY customer_id;
| customer_id | sum | count |
|---|---|---|
| B | 40 | 3 |
| A | 25 | 2 |