Common Table Expressions (CTEs)
Name your query steps with WITH — no more nested subquery spaghetti
WITH ... AS: Named Steps
A CTE (Common Table Expression) is a named temporary result set defined with WITH. You reference it by name in the main query as if it were a regular table. Here's why CTEs matter:
How CTEs Work
Named temporary result sets
- WITH name AS (query) — define a named step
- Chain multiple CTEs with commas
- Each CTE can reference previously defined CTEs
- CTEs exist only for the duration of the query
CTE vs Subquery vs View
Three ways to reuse query logic
CTE Pipeline
How multi-step CTEs execute
CTE Patterns
Common real-world structures
- Multi-step aggregation: raw → grouped → ranked
- Recursive CTEs: hierarchies, sequences, trees
- Reuse: reference same CTE twice in final SELECT
- Self-documenting: CTE names describe each step
Best Practices
Writing clean CTEs
- Name CTEs after what they contain, not what they do
- Keep each CTE focused on one transformation
- Avoid 5+ CTEs — consider views or temp tables
- Comment complex CTEs explaining the "why"
WITHStarts the CTE definition blockAS (...)The query that defines this CTEComma-separatedChain multiple CTEs before the final SELECT| id | customer_id | total |
|---|---|---|
| 5001 | C1001 | 59.98 |
| 5002 | C1002 | 449 |
| 5003 | C1001 | 12.5 |
| 5004 | C1003 | 89.99 |
| 5005 | C1006 | 245 |
| 5006 | C1005 | 159 |
| 5007 | C1004 | 45.5 |
| 5008 | C1009 | 79 |
| 5009 | C1012 | 425 |
| 5010 | C1007 | 18.99 |
| 5011 | C1008 | 134 |
| 5012 | C1010 | 65.5 |
| id | name |
|---|---|
| C1001 | Aarav Sharma |
| C1002 | Sara Chen |
| C1003 | James Wilson |
| C1004 | Maria Garcia |
| C1005 | Yuki Tanaka |
| C1006 | Priya Patel |
| C1007 | Alex Johnson |
| C1008 | Chen Wei |
| C1009 | Emma Brown |
| C1010 | Omar Hassan |
| C1011 | Lena Muller |
| C1012 | Ravi Kumar |
Worked Example
Find customers who spent above the average total spend.
| name | total_spent |
|---|---|
| Sara Chen | 449 |
| Ravi Kumar | 425 |
| Priya Patel | 245 |
Key Concepts
Pro Tip
Nested subqueries become unreadable past 2–3 levels. CTEs let you name each step so logic reads like a recipe — this is how production analytics SQL is written.
When to Use
Multi-step revenue reports, building metrics from raw data, ranked analyses, any query requiring intermediate computations.
Using a CTE, find the average order total per customer, then show customers whose average order exceeds 100. Display name and avg_order (rounded to 2 decimals).