Listing multiple CTEs separated by commas creates a pipeline in which each later CTE can reference an earlier one. This organizes complex batch processing as a sequence of named steps.
WITH step1 AS ( SELECT user_id, COUNT(*) AS order_count FROM orders GROUP BY user_id ), step2 AS ( -- can reference step1 SELECT *, CASE WHEN order_count >= 5 THEN 'Loyal' ELSE 'General' END AS segment FROM step1 ) SELECT * FROM step2;
From the orders table below, calculate each user’s R (days since the most recent purchase), F (purchase count), and M (total purchase amount), assign each metric a score from 1 to 3, and classify the final segment.
Reference date: 2024-05-01. R: within 30 days = 3, within 60 days = 2, otherwise = 1. F: 3 or more purchases = 3, 2 purchases = 2, 1 purchase = 1. M: at least 100000 = 3, at least 50000 = 2, otherwise = 1.
Classify the final segment as “VIP” when total_score is at least 8, “Loyal” when it is at least 6, and “General” otherwise.
| order_id | user_id | order_date | amount |
|---|---|---|---|
| 1 | U01 | 2024-04-20 | 50000 |
| 2 | U01 | 2024-04-28 | 70000 |
| 3 | U01 | 2024-04-30 | 30000 |
| 4 | U02 | 2024-03-10 | 120000 |
| 5 | U02 | 2024-03-25 | 40000 |
| 6 | U03 | 2024-01-15 | 30000 |
| 7 | U04 | 2024-04-25 | 200000 |
| 8 | U04 | 2024-04-29 | 150000 |
| user_id | r_score | f_score | m_score | total_score | segment |
|---|---|---|---|---|---|
| U01 | 3 | 3 | 3 | 9 | VIP |
| U04 | 3 | 2 | 3 | 8 | VIP |
| U02 | 2 | 2 | 3 | 7 | Loyal |
| U03 | 1 | 1 | 1 | 3 | General |
- Read every model answer, explanation and table-transition visualization across all 48 advanced sets (240 questions)
- One-time purchase — no subscription. Future advanced sets are included
- Background, problem and expected output stay free
When tied scores must include everyone through the tied third place, DENSE_RANK() is the right choice. Understand how it differs from ROW_NUMBER.
SELECT player, score, ROW_NUMBER() OVER (ORDER BY score DESC) AS rn, -- always assign consecutive numbers, even for ties RANK() OVER (ORDER BY score DESC) AS rnk, -- ties share a rank; the next rank is skipped DENSE_RANK() OVER (ORDER BY score DESC) AS dr; -- ties share a rank; rank numbers do not skip
From the game_scores table below, rank players within each game using DENSE_RANK and return everyone ranked third or higher. Show every tied player at the same rank.
| game_id | player_name | score |
|---|---|---|
| G01 | Alice | 9500 |
| G01 | Bob | 8200 |
| G01 | Carol | 8200 |
| G01 | Dave | 7800 |
| G01 | Eve | 7100 |
| G02 | Frank | 6000 |
| G02 | Grace | 6000 |
| G02 | Hank | 5500 |
| G02 | Iris | 4800 |
| game_id | player_name | score | rank |
|---|---|---|---|
| G01 | Alice | 9500 | 1 |
| G01 | Bob | 8200 | 2 |
| G01 | Carol | 8200 | 2 |
| G01 | Dave | 7800 | 3 |
| G02 | Frank | 6000 | 1 |
| G02 | Grace | 6000 | 1 |
| G02 | Hank | 5500 | 2 |
| G02 | Iris | 4800 | 3 |
※ G01 Eve (7100) is excluded because DENSE_RANK = 4
- Read every model answer, explanation and table-transition visualization across all 48 advanced sets (240 questions)
- One-time purchase — no subscription. Future advanced sets are included
- Background, problem and expected output stay free
Months with no sales have no rows in the orders table. However, a monthly report may still need to include months with zero sales. LEFT JOIN + COALESCE is the standard pattern.
SELECT m.month, COALESCE(s.total_sales, 0) AS total_sales -- replace NULL with 0 FROM months m -- master list of all months LEFT JOIN sales_summary s -- exists only for months with sales (some months become NULL) ON m.month = s.month; -- join by month
Create a monthly summary for every month from January through June 2024. For months with no sales, set total_sales = 0 and order_count = 0.
| order_id | order_month | amount |
|---|---|---|
| 1 | 2024-01 | 30000 |
| 2 | 2024-01 | 50000 |
| 3 | 2024-03 | 80000 |
| 4 | 2024-05 | 40000 |
| 5 | 2024-05 | 60000 |
| 6 | 2024-06 | 90000 |
| month |
|---|
| 2024-01 |
| 2024-02 |
| 2024-03 |
| 2024-04 |
| 2024-05 |
| 2024-06 |
| month | total_sales | order_count |
|---|---|---|
| 2024-01 | 80000 | 2 |
| 2024-02 | 0 | 0 |
| 2024-03 | 80000 | 1 |
| 2024-04 | 0 | 0 |
| 2024-05 | 100000 | 2 |
| 2024-06 | 90000 | 1 |
- Read every model answer, explanation and table-transition visualization across all 48 advanced sets (240 questions)
- One-time purchase — no subscription. Future advanced sets are included
- Background, problem and expected output stay free
FIRST_VALUE() and LAST_VALUE() return values from the first and last rows in a window. They are useful for purchase-history analysis such as showing each user’s first and latest product on one row.
FIRST_VALUE(product) OVER ( PARTITION BY user_id -- independent for each user ORDER BY order_date -- days → of rowsis timespurchase ) AS first_product LAST_VALUE(product) OVER ( PARTITION BY user_id ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING -- look at all rows — important ) AS last_product
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING in “allrows”please。From the purchase_history table below, return each user’s first purchase date, first product, latest purchase date, and latest product on one row. Return exactly one row per user.
| user_id | order_date | product |
|---|---|---|
| U01 | 2024-01-10 | Apple |
| U01 | 2024-02-20 | Banana |
| U01 | 2024-04-05 | Orange |
| U02 | 2024-01-15 | Green tea |
| U02 | 2024-03-30 | Coffee |
| U03 | 2024-02-01 | Water |
| user_id | first_date | first_product | last_date | last_product |
|---|---|---|---|---|
| U01 | 2024-01-10 | Apple | 2024-04-05 | Orange |
| U02 | 2024-01-15 | Green tea | 2024-03-30 | Coffee |
| U03 | 2024-02-01 | Water | 2024-02-01 | Water |
- Read every model answer, explanation and table-transition visualization across all 48 advanced sets (240 questions)
- One-time purchase — no subscription. Future advanced sets are included
- Background, problem and expected output stay free
A recursive CTE (WITH RECURSIVE) is a self-referencing query. It expands data with hierarchical parent-child relationships, such as category trees, organization charts, and comment threads.
WITH RECURSIVE tree AS ( -- Anchor: get the first row (root node) SELECT id, parent_id, name, 0 AS depth FROM categories WHERE parent_id IS NULL -- no parent = root UNION ALL -- connect the anchor and recursive members (do not remove duplicates) -- Recursive member: use the previous step to get children SELECT c.id, c.parent_id, c.name, t.depth + 1 FROM categories c INNER JOIN tree t -- reference tree from the previous step (recursive) ON c.parent_id = t.id ) SELECT * FROM tree;
The categories table below stores parent-child relationships for product categories. Expand every level with a recursive CTE and display each category’s depth and hierarchy path (for example: Electronics > Smartphone > Android).
| id | parent_id | name |
|---|---|---|
| 1 | NULL | Electronics |
| 2 | 1 | Smartphone |
| 3 | 1 | PC |
| 4 | 2 | Android |
| 5 | 2 | iPhone |
| 6 | 3 | Notebook PC |
| 7 | 3 | Desktop |
| id | name | depth | path |
|---|---|---|---|
| 1 | Electronics | 0 | Electronics |
| 2 | Smartphone | 1 | Electronics > Smartphone |
| 3 | PC | 1 | Electronics > PC |
| 4 | Android | 2 | Electronics > Smartphone > Android |
| 5 | iPhone | 2 | Electronics > Smartphone > iPhone |
| 6 | Notebook PC | 2 | Electronics > PC > Notebook PC |
| 7 | Desktop | 2 | Electronics > PC > Desktop |
- Read every model answer, explanation and table-transition visualization across all 48 advanced sets (240 questions)
- One-time purchase — no subscription. Future advanced sets are included
- Background, problem and expected output stay free