WITH (Common Table Expressions - CTEs)
Feb 23, 2026
·
5
min read
Category: Subqueries / Query Structure
Platform Support:
✅ Snowflake | ✅ BigQuery | ✅ Databricks
Description
WITH clause (Common Table Expression or CTE) creates temporary named result sets that exist only during query execution. CTEs improve query readability, enable recursive queries, and allow you to reference the same subquery multiple times. Think of them as temporary views that exist for a single query.
Syntax
Platform-Specific Notes
Snowflake:
Full support for recursive CTEs
CTEs can be materialized for performance
Supports QUALIFY with CTEs
BigQuery:
Full support for recursive CTEs
Optimizes CTE execution automatically
Supports WITH in subqueries
Databricks:
Full support for recursive CTEs
Spark optimization for CTE execution
Can cache CTE results
Example 1: Basic CTE for Readability
All Platforms:
Sample Data:
customers:
customer_id | name |
|---|---|
1 | John Smith |
2 | Maria Garcia |
3 | Sarah Johnson |
orders:
order_id | customer_id | order_date | total |
|---|---|---|---|
101 | 1 | 2024-01-15 | 250.00 |
102 | 2 | 2024-01-20 | 180.00 |
103 | 1 | 2024-01-25 | 320.00 |
Result:
customer_id | name | total_orders | total_spent |
|---|---|---|---|
1 | John Smith | 2 | 570.00 |
2 | Maria Garcia | 1 | 180.00 |
Example 2: Multiple CTEs Building on Each Other
All Platforms:
Sample Data (orders table):
order_id | order_date | total |
|---|---|---|
101 | 2024-01-15 | 250.00 |
102 | 2024-01-20 | 180.00 |
103 | 2024-02-10 | 320.00 |
104 | 2024-02-15 | 280.00 |
105 | 2024-03-05 | 450.00 |
Result:
month | revenue | order_count | revenue_change | growth_rate_pct | performance_rating |
|---|---|---|---|---|---|
2024-01-01 | 430.00 | 2 | 0.00 | 0.00 | Good |
2024-02-01 | 600.00 | 2 | 170.00 | 39.53 | Excellent |
2024-03-01 | 450.00 | 1 | -150.00 | -25.00 | Poor |
Example 3: Recursive CTE - Organizational Hierarchy
All Platforms:
Sample Data (employees table):
employee_id | name | manager_id | title |
|---|---|---|---|
1 | Alice Chen | NULL | CEO |
2 | Bob Smith | 1 | VP Sales |
3 | Carol White | 1 | VP Engineering |
4 | David Brown | 2 | Sales Manager |
5 | Emma Davis | 3 | Engineering Lead |
6 | Frank Wilson | 4 | Sales Rep |
Result:
employee_id | name | title | level | hierarchy_path |
|---|---|---|---|---|
1 | Alice Chen | CEO | 1 | Alice Chen |
2 | Bob Smith | VP Sales | 2 | Alice Chen > Bob Smith |
3 | Carol White | VP Engineering | 2 | Alice Chen > Carol White |
4 | David Brown | Sales Manager | 3 | Alice Chen > Bob Smith > David Brown |
5 | Emma Davis | Engineering Lead | 3 | Alice Chen > Carol White > Emma Davis |
6 | Frank Wilson | Sales Rep | 4 | Alice Chen > Bob Smith > David Brown > Frank Wilson |
Example 4: Recursive CTE - Date Series Generation
All Platforms:
Result (first 7 rows):
date | day_of_week | day_type |
|---|---|---|
2024-01-01 | Monday | Weekday |
2024-01-02 | Tuesday | Weekday |
2024-01-03 | Wednesday | Weekday |
2024-01-04 | Thursday | Weekday |
2024-01-05 | Friday | Weekday |
2024-01-06 | Saturday | Weekend |
2024-01-07 | Sunday | Weekend |
Example 5: Complex Analysis with Multiple CTEs
All Platforms:
Sample Result:
segment | customer_count | avg_lifetime_value | avg_orders | avg_days_inactive | pct_of_customers |
|---|---|---|---|---|---|
VIP | 45 | 2150.50 | 8.2 | 12 | 15.00 |
Premium | 120 | 685.25 | 4.1 | 28 | 40.00 |
Standard | 135 | 245.80 | 1.8 | 45 | 45.00 |
CTE vs Subquery vs Temporary Table
Feature | CTE | Subquery | Temp Table |
|---|---|---|---|
Readability | Excellent | Poor | Good |
Reusability in query | Yes | No | Yes |
Persists after query | No | No | Yes (session) |
Can be recursive | Yes | No | No |
Performance | Optimized | Optimized | May be faster |
Scope | Single query | Single query | Session |
Common Use Cases
Improve readability: Break complex queries into logical steps
Recursive queries: Hierarchies, date series, graph traversal
Multiple references: Use same subquery multiple times
Step-by-step logic: Build analysis incrementally
Testing/debugging: Isolate and test query components
Data pipeline: Chain transformations clearly
Performance Considerations
CTEs are typically optimized by query planner
May be materialized or inlined depending on usage
Recursive CTEs need termination condition
For very large intermediate results, consider temp tables
Most modern databases optimize CTEs well
Best Practices
Use descriptive names: Make CTE purpose clear
One logical step per CTE: Keep CTEs focused
Order logically: Build from simple to complex
Comment complex logic: Explain business rules
Limit recursion depth: Prevent infinite loops
Test incrementally: Validate each CTE separately
Consider materialization: For reused expensive CTEs





