Chaining multiple CTEs (Common Table Expressions) lets you split the transformation from raw data → evaluation → aggregation → ranking into clear stages. In particular, conditional aggregation (SUM(CASE WHEN ...)) is a common pattern for counting “achieved / not achieved” rows by summing a flag column.
WITH eval AS ( SELECT ..., CASE WHEN value >= target THEN 1 ELSE 0 END AS achieved FROM raw_table ), scored AS ( SELECT company_name, SUM(achieved) AS metrics_achieved, ROUND(SUM(achieved) * 100.0 / COUNT(*), 1) AS achievement_rate FROM eval GROUP BY company_name )
FROM. Splitting the logic into stages greatly improves readability and debuggability. A two-stage design—aggregate with GROUP BY inside a CTE, then apply a window function outside—is a standard practice.The competitor_metrics table stores KPI actuals and targets for each company. Calculate each company's KPI achievement count, achievement rate, and overall rank, remembering that a lower churn rate is better. Return company_name, metrics_achieved, total_metrics, achievement_rate, overall_rank, sorted by overall_rank ascending and then company_name ascending.
| company_name | metric_name | value | target |
|---|---|---|---|
| AlphaTech | Revenue growth (%) | 18.8 | 15.0 |
| AlphaTech | Market share (%) | 36.5 | 35.0 |
| AlphaTech | NPS | 42 | 50 |
| AlphaTech | Churn rate (%) | 3.2 | 4.0 |
| BetaSoft | Revenue growth (%) | 19.2 | 15.0 |
| BetaSoft | Market share (%) | 28.0 | 30.0 |
| BetaSoft | NPS | 55 | 50 |
| BetaSoft | Churn rate (%) | 4.8 | 4.0 |
| GammaSys | Revenue growth (%) | 22.2 | 15.0 |
| GammaSys | Market share (%) | 18.0 | 20.0 |
| GammaSys | NPS | 38 | 50 |
| GammaSys | Churn rate (%) | 2.5 | 4.0 |
| DeltaNet | Revenue growth (%) | 14.0 | 15.0 |
| DeltaNet | Market share (%) | 15.0 | 35.0 |
| DeltaNet | NPS | 35 | 50 |
| DeltaNet | Churn rate (%) | 5.5 | 4.0 |
Only Churn rate (%) is a reverse-direction metric: lower values are better.
Expected output (overall_rank ascending → company_name ascending):
| company_name | metrics_achieved | total_metrics | achievement_rate | overall_rank |
|---|---|---|---|---|
| AlphaTech | 3 | 4 | 75.0 | 1 |
| BetaSoft | 2 | 4 | 50.0 | 2 |
| GammaSys | 2 | 4 | 50.0 | 2 |
| DeltaNet | 0 | 4 | 0.0 | 3 |
AlphaTech misses NPS but achieves the other three metrics and ranks first. BetaSoft and GammaSys tie at a 50.0% achievement rate and both rank second. Because this uses DENSE_RANK, DeltaNet is third rather than fourth.
- 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
Specifying a window-function frame clause (ROWS BETWEEN) gives precise control over how many preceding and following rows are included in an aggregation. A moving average and a cumulative total are representative applications.
| Frame clause | Meaning | Typical use |
|---|---|---|
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW | Previous 2 rows through the current row (3 rows total) | 3-period moving average |
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW | First row through the current row (full cumulative range) | Cumulative revenue / count |
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING | Current row through the last row | Remaining total |
AVG(revenue) OVER ( PARTITION BY company_name ORDER BY quarter ROWS BETWEEN 2 PRECEDING AND CURRENT ROW -- 3-quarter moving average )
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW (cumulative). To target only the most recent N rows, as a moving average does, always specify ROWS BETWEEN.For each company's quarterly revenue in the quarterly_revenue table, calculate a 3-quarter moving average (moving_avg_3q) and cumulative revenue (cumulative_rev). Return company_name, quarter, revenue, moving_avg_3q, cumulative_rev, sorted by company_name ascending and then quarter ascending.
| company_name | quarter | revenue |
|---|---|---|
| AlphaTech | 2024Q1 | 95 |
| AlphaTech | 2024Q2 | 100 |
| AlphaTech | 2024Q3 | 108 |
| AlphaTech | 2024Q4 | 115 |
| BetaSoft | 2024Q1 | 68 |
| BetaSoft | 2024Q2 | 72 |
| BetaSoft | 2024Q3 | 75 |
| BetaSoft | 2024Q4 | 78 |
| GammaSys | 2024Q1 | 38 |
| GammaSys | 2024Q2 | 42 |
| GammaSys | 2024Q3 | 45 |
| GammaSys | 2024Q4 | 50 |
Revenue unit: JPY 100 million
Expected output (company_name ascending → quarter ascending):
| company_name | quarter | revenue | moving_avg_3q | cumulative_rev |
|---|---|---|---|---|
| AlphaTech | 2024Q1 | 95 | 95.0 | 95 |
| AlphaTech | 2024Q2 | 100 | 97.5 | 195 |
| AlphaTech | 2024Q3 | 108 | 101.0 | 303 |
| AlphaTech | 2024Q4 | 115 | 107.7 | 418 |
| BetaSoft | 2024Q1 | 68 | 68.0 | 68 |
| BetaSoft | 2024Q2 | 72 | 70.0 | 140 |
| BetaSoft | 2024Q3 | 75 | 71.7 | 215 |
| BetaSoft | 2024Q4 | 78 | 75.0 | 293 |
| GammaSys | 2024Q1 | 38 | 38.0 | 38 |
| GammaSys | 2024Q2 | 42 | 40.0 | 80 |
| GammaSys | 2024Q3 | 45 | 41.7 | 125 |
| GammaSys | 2024Q4 | 50 | 45.7 | 175 |
Q1 has no preceding row, so its average uses only the current row. For AlphaTech Q4, (100+108+115)/3=107.7. The cumulative value is simply the annual total.
- 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
PERCENT_RANK and CUME_DIST both express a row's relative position within a group as a percentage, but their formulas differ.
| Function | Formula | Minimum | Maximum | Interpretation |
|---|---|---|---|---|
PERCENT_RANK() | (rank − 1) / (n − 1) | 0.0 (minimum row) | 1.0 (maximum row) | Share of values smaller than this value |
CUME_DIST() | rank / n | 1/n (minimum row) | 1.0 (maximum row) | Share of values less than or equal to this value |
PERCENT_RANK() OVER ( PARTITION BY category ORDER BY annual_revenue -- Ascending: the maximum is 100% ) * 100 AS pct_rank
For each company's category revenue in the category_performance table, calculate the within-category percentile rank (pct_rank) and cumulative distribution (cume_dist_pct) on a 0–100 scale, rounded to one decimal place. Return category, company_name, annual_revenue, pct_rank, cume_dist_pct, sorted by category ascending and then annual_revenue descending.
| company_name | category | annual_revenue |
|---|---|---|
| AlphaTech | Cloud | 4200 |
| BetaSoft | Cloud | 2800 |
| GammaSys | Cloud | 1500 |
| DeltaNet | Cloud | 800 |
| EpsilonIO | Cloud | 500 |
| BetaSoft | Security | 2200 |
| AlphaTech | Security | 1200 |
| DeltaNet | Security | 1200 |
| GammaSys | Security | 900 |
| EpsilonIO | Security | 600 |
Annual revenue unit: JPY 100 million
Expected output (category ascending → annual_revenue descending):
| category | company_name | annual_revenue | pct_rank | cume_dist_pct |
|---|---|---|---|---|
| Cloud | AlphaTech | 4200 | 100.0 | 100.0 |
| Cloud | BetaSoft | 2800 | 75.0 | 80.0 |
| Cloud | GammaSys | 1500 | 50.0 | 60.0 |
| Cloud | DeltaNet | 800 | 25.0 | 40.0 |
| Cloud | EpsilonIO | 500 | 0.0 | 20.0 |
| Security | BetaSoft | 2200 | 100.0 | 100.0 |
| Security | AlphaTech | 1200 | 50.0 | 80.0 |
| Security | DeltaNet | 1200 | 50.0 | 80.0 |
| Security | GammaSys | 900 | 25.0 | 40.0 |
| Security | EpsilonIO | 600 | 0.0 | 20.0 |
AlphaTech and DeltaNet tie at 1200 in Security. For a tie, CUME_DIST uses the four rows at or below that value as the numerator, producing 80.0%.
- 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() attaches the value from the “first row” of the window defined in the OVER clause to every row. Combined with ORDER BY score DESC, it retrieves the maximum value—the leader's value—in each partition.
| Function | What it returns | Use |
|---|---|---|
FIRST_VALUE(col) | Value from the first row of the window | Category leader's value or name |
LAST_VALUE(col) | Value from the last row of the window* | Category's lowest value |
NTH_VALUE(col,n) | Value from the n-th row of the window | Second- or third-place value |
FIRST_VALUE(company_name) OVER ( PARTITION BY category ORDER BY composite_score DESC -- Descending: the first row has the highest score ) AS leader_name
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW (cumulative through the current row), so it always returns “your own value”. To get the final row's value, you need ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.From the product_scores table, calculate the leader company name (leader_name), leader score (leader_score), and score gap to the leader (gap_to_leader) for each category. Use a CTE. Return category, company_name, composite_score, leader_name, leader_score, gap_to_leader, sorted by category ascending and then composite_score descending.
| company_name | category | composite_score |
|---|---|---|
| AlphaTech | Cloud | 88.5 |
| BetaSoft | Cloud | 79.2 |
| GammaSys | Cloud | 71.0 |
| DeltaNet | Cloud | 65.3 |
| BetaSoft | Security | 91.3 |
| AlphaTech | Security | 74.1 |
| GammaSys | Security | 68.7 |
| DeltaNet | Security | 55.2 |
| AlphaTech | Data Analytics | 83.4 |
| GammaSys | Data Analytics | 80.1 |
| BetaSoft | Data Analytics | 76.8 |
| DeltaNet | Data Analytics | 62.0 |
Expected output (category ascending → composite_score descending):
| category | company_name | composite_score | leader_name | leader_score | gap_to_leader |
|---|---|---|---|---|---|
| Cloud | AlphaTech | 88.5 | AlphaTech | 88.5 | 0.0 |
| Cloud | BetaSoft | 79.2 | AlphaTech | 88.5 | -9.3 |
| Cloud | GammaSys | 71.0 | AlphaTech | 88.5 | -17.5 |
| Cloud | DeltaNet | 65.3 | AlphaTech | 88.5 | -23.2 |
| Security | BetaSoft | 91.3 | BetaSoft | 91.3 | 0.0 |
| Security | AlphaTech | 74.1 | BetaSoft | 91.3 | -17.2 |
| Security | GammaSys | 68.7 | BetaSoft | 91.3 | -22.6 |
| Security | DeltaNet | 55.2 | BetaSoft | 91.3 | -36.1 |
| Data Analytics | AlphaTech | 83.4 | AlphaTech | 83.4 | 0.0 |
| Data Analytics | GammaSys | 80.1 | AlphaTech | 83.4 | -3.3 |
| Data Analytics | BetaSoft | 76.8 | AlphaTech | 83.4 | -6.6 |
| Data Analytics | DeltaNet | 62.0 | AlphaTech | 83.4 | -21.4 |
The leader differs by category; only BetaSoft leads in Security. A gap_to_leader of 0 identifies each category's leader at a glance.
- 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 serial CTE chain organizes a complex data transformation into steps such as “calculate period-over-period change → classify → aggregate”. This question demonstrates how to connect three constructs: LAG, CASE WHEN, and SUM OVER.
WITH step1 AS ( SELECT ..., LAG(val) OVER (PARTITION BY grp ORDER BY t) AS prev_val FROM src ), step2 AS ( SELECT ..., val - prev_val AS delta, CASE WHEN val > prev_val THEN '▲ Growth' ELSE '▼ Decline' END AS trend FROM step1 WHERE prev_val IS NOT NULL -- Exclude the NULL at the first period ) SELECT ..., SUM(CASE WHEN trend = '▲ Growth' THEN 1 ELSE 0 END) OVER (PARTITION BY company_name ORDER BY period) AS expanding_periods FROM step2;
SELECT * FROM step1, layer step2 on top, and aggregate at the end—a gradual development process.The market_share_trend table stores semiannual market share for four companies. Chain two CTEs to calculate ① the period-over-period share change (share_delta), ② the growth/decline label (trend), and ③ the cumulative number of expanding periods (expanding_periods). Exclude the first period (the row where prev_share is NULL). Return company_name, period, market_share_pct, prev_share, share_delta, trend, expanding_periods, sorted by company_name ascending and then period ascending.
| company_name | period | market_share_pct |
|---|---|---|
| AlphaTech | 2023H1 | 38.5 |
| AlphaTech | 2023H2 | 40.2 |
| AlphaTech | 2024H1 | 42.0 |
| BetaSoft | 2023H1 | 30.1 |
| BetaSoft | 2023H2 | 28.5 |
| BetaSoft | 2024H1 | 26.8 |
| DeltaNet | 2023H1 | 13.0 |
| DeltaNet | 2023H2 | 12.3 |
| DeltaNet | 2024H1 | 11.7 |
| GammaSys | 2023H1 | 18.4 |
| GammaSys | 2023H2 | 19.0 |
| GammaSys | 2024H1 | 19.5 |
Expected output (company_name ascending → period ascending; first periods excluded, 8 rows):
| company_name | period | market_share_pct | prev_share | share_delta | trend | expanding_periods |
|---|---|---|---|---|---|---|
| AlphaTech | 2023H2 | 40.2 | 38.5 | 1.7 | ▲ Growth | 1 |
| AlphaTech | 2024H1 | 42.0 | 40.2 | 1.8 | ▲ Growth | 2 |
| BetaSoft | 2023H2 | 28.5 | 30.1 | -1.6 | ▼ Decline | 0 |
| BetaSoft | 2024H1 | 26.8 | 28.5 | -1.7 | ▼ Decline | 0 |
| DeltaNet | 2023H2 | 12.3 | 13.0 | -0.7 | ▼ Decline | 0 |
| DeltaNet | 2024H1 | 11.7 | 12.3 | -0.6 | ▼ Decline | 0 |
| GammaSys | 2023H2 | 19.0 | 18.4 | 0.6 | ▲ Growth | 1 |
| GammaSys | 2024H1 | 19.5 | 19.0 | 0.5 | ▲ Growth | 2 |
AlphaTech and GammaSys expanded for two consecutive periods (expanding_periods=2). BetaSoft and DeltaNet declined in both periods (expanding_periods=0).
- 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