INSERT INTO sale (id, book_id, sale_date, quantity, customer_id) VALUES
(1, 1, '2024-01-15', 2, 1),
(2, 1, '2024-01-16', 1, 2),
(3, 2, '2024-01-15', 3, 1),
(4, 3, '2024-01-17', 1, 3),
(5, 4, '2024-01-18', 2, 4),
(6, 1, '2024-01-19', 1, 3),
(7, 2, '2024-01-20', 2, 4),
(8, 3, '2024-01-21', 1, 3);
(1, 1, '2025-01-15', 2, 1),
(2, 1, '2025-01-16', 1, 2),
(3, 2, '2025-01-15', 3, 1),
(4, 3, '2025-01-17', 1, 3),
(5, 4, '2025-01-18', 2, 4),
(6, 1, '2025-01-19', 1, 3),
(7, 2, '2025-01-20', 2, 4),
(8, 3, '2025-01-21', 1, 3);
INSERT INTO customer (id, name, joined_date) VALUES
(1, 'John Smith', '2023-12-01'),
(2, 'Jane Doe', '2023-12-15'),
(3, 'Bob Wilson', '2024-01-01'),
(4, 'Alice Brown', '2024-01-10');
(1, 'John Smith', '2024-12-01'),
(2, 'Jane Doe', '2024-12-15'),
(3, 'Bob Wilson', '2025-01-01'),
(4, 'Alice Brown', '2025-01-10');
```
---
@ -69,7 +69,7 @@ SELECT * FROM cte_name;
Let's look at some simple examples to get the idea.
### Example 1: Find all engineering books
### Example: Find all engineering books
Query below is a simple CTE to find all the engineering books:
@ -82,7 +82,7 @@ WITH engineering_books AS (
SELECT * FROM engineering_books;
```
### Example 2: Programming books and their sales
### Example: Programming books and their sales
Say we want to find all programming books and their total sales:
@ -157,7 +157,9 @@ Now that we have 3 different simpler queries instead of one complex query, it's
As we saw in the query above, you can define multiple CTEs separated by commas. CTEs can be used in the other CTEs as well.
For example, let's say we want to find the top 3 selling books and the number of new customers (joined date > 2024-01-01) who bought them.
### Example: Top 3 selling books and new customers
For example, let's say we want to find the top 3 selling books and the number of new customers (joined date > 2025-01-01) who bought them.
```sql
-- CTE 1: Find the top 3 selling books
@ -170,11 +172,11 @@ WITH top_selling_books AS (
ORDER BY SUM(quantity) DESC
LIMIT 3
),
-- CTE 2: Find all customers who joined after 2024-01-01
-- CTE 2: Find all customers who joined after 2025-01-01
recent_customers AS (
SELECT *
FROM customer
WHERE joined_date >= '2024-01-01'
WHERE joined_date >= '2025-01-01'
)
-- Main query: Find the books and the number of new customers who bought them
SELECT
@ -188,6 +190,93 @@ INNER JOIN recent_customers c ON c.id = s.customer_id
GROUP BY b.title, tsb.total_sold;
```
Let's break this query down to understand it better:
> `top_selling_books` CTE finds the top 3 selling books
| book_id | total_sold |
| ------- | ---------- |
| 2 | 5 |
| 1 | 4 |
| 3 | 2 |
> `recent_customers` CTE finds all customers who joined after 2025-01-01
| id | name | joined_date |
| --- | ----------- | ----------- |
| 3 | Bob Wilson | 2025-01-01 |
| 4 | Alice Brown | 2025-01-10 |
Finally the main query joins the `top_selling_books` with `book` (to get the title) and `sale` (to get the count of sales) and `recent_customers` (to ensure we only get customers who joined after 2025-01-01). The final result is:
Finally we have cross join in the main query to join each purchase to each row in the `spending_metrics` so that we can compare each customer to the overall spending metrics.
| id | name | purchases | total_spent | avg_per_purchase | spending_category |