PRO SQL Modules
SQL Basics1h 20m • 4 lessons
Multiple Tables1h 40m • 5 lessons
Query Restructuring40m • 2 lessons
Data Transformation1h 40m • 5 lessons
Analytical SQL2h • 6 lessons
Common Table Expressions (CTE)

Dan Lee
Lesson Objectives
By the end of this lesson, you will:
- Learn how to use WITH to define Common Table Expressions (CTEs)
- Understand how CTEs improve query readability and reusability
- Write SQL queries to analyze Google Ads campaign data using CTEs
🎬 Scenario: Simplifying Google Ads Performance Reports
Your manager at Google Ads, Jordan, wants a report on high-converting campaigns, but their existing query is difficult to read and maintain.
Can you break the query into smaller logical steps so we can easily modify it later?
Your task is to use Common Table Expressions (CTEs) to simplify the analysis of Google Ads performance.
google_ads_campaigns:
campaign_id | user_id | campaign_name | ad_type | start_date | end_date | budget | impressions | clicks | conversions |
---|---|---|---|---|---|---|---|---|---|
1 | 1 | Growth Hackers Special | Search | 2024-01-10T00:00:00 | 2024-02-10T00:00:00 | 5000 | 500000 | 12000 | 800 |
2 | 2 | BigTech Awareness | Display | 2024-01-05T00:00:00 | 2024-02-20T00:00:00 | 20000 | 2000000 | 50000 | 3000 |
3 | 3 | Ecom Holiday Sales | Shopping | 2023-11-15T00:00:00 | 2024-01-15T00:00:00 | 10000 | 750000 | 22000 | 1500 |
4 | 4 | Fashion Hub Summer | Video | 2024-02-01T00:00:00 | 2024-03-01T00:00:00 | 15000 | 900000 | 18000 | 1200 |
5 | 5 | HealthyLife Brand Push | Search | 2024-01-20T00:00:00 | 2024-03-10T00:00:00 | 8000 | 600000 | 15000 | 900 |
1. Understanding Common Table Expressions (CTEs)
A CTE allows you to define a temporary result set that can be referenced inside a query.
CTEs make queries:
- More readable by breaking them into logical steps.
- Reusable since the CTE can be referenced multiple times.
Syntax
1WITH cte_name AS (
2 SELECT column1, column2
3 FROM table_name
4 WHERE condition
5)
6SELECT * FROM cte_name;
- The WITH clause defines the CTE, which is like a temporary table.
- The main query selects from the CTE instead of a complex inline subquery.
2. Using CTEs to Calculate Conversion Rates
Instead of writing a long, nested query, we can use a CTE to first calculate campaign conversion rates and then filter the results.
Example Query: Calculating Conversion Rate Using CTE
1WITH conversion_rates AS (
2 SELECT campaign_name,
3 conversions * 100.0 / clicks AS conversion_rate
4 FROM google_ads_campaigns
5)
6SELECT * FROM conversion_rates
7WHERE conversion_rate > 5
8ORDER BY conversion_rate DESC;
campaign_name | conversion_rate |
---|---|
Ecom Holiday Sales | 6.82% |
Growth Hackers Special | 6.67% |
Fashion Hub Summer | 6.67% |
What’s Happening?
- The CTE conversion_rates first calculates the conversion rate for each campaign.
- The main query selects from the CTE and filters campaigns above 5% conversion.
3. Using Multiple CTEs in One Query
CTEs can be chained together for more complex analysis.
For example, we can:
- Calculate total ad spend per user (user_spend).
- Find users who spent more than the average (high_spenders).
Example Query: Finding Top Ad Spenders Using Multiple CTEs
1WITH user_spend AS (
2 SELECT user_id, company, SUM(ad_spend_total) AS total_spent
3 FROM google_ads_users
4 GROUP BY user_id, company
5),
6high_spenders AS (
7 SELECT user_id, company, total_spent
8 FROM user_spend
9 WHERE total_spent > (SELECT AVG(total_spent) FROM user_spend)
10)
11SELECT * FROM high_spenders
12ORDER BY total_spent DESC;
user_id | company | total_spent |
---|---|---|
2 | BigTech Corp | 200000 |
4 | FashionHub | 120000 |
What’s Happening?
- The first CTE (user_spend) calculates total ad spend per user.
- The second CTE (high_spenders) filters out users below average spend.
- The main query selects from high_spenders, displaying only top spenders.
✍️ SQL Exercises
Exercise 1: Finding High-Converting Campaigns
Jordan needs a list of campaigns with conversion rates above 5% using a CTE.
Filter condition:
- Retrieve campaign name and conversion rate.
- Only include campaigns with conversion rates above 5%.
- Sort by conversion_rate in descending order.
campaign_name | conversion_rate |
---|---|
“Ecom Holiday Sales” | 6.818181818181818 |
“Growth Hackers Special” | 6.666666666666667 |
“Fashion Hub Summer” | 6.666666666666667 |
“BigTech Awareness” | 6 |
“HealthyLife Brand Push” | 6 |
Write an SQL query to return the requested data.
Exercise 2: Identifying High Ad Spenders Using CTEs
Jordan also wants to find the advertisers who spent more than the average using CTEs.
Filter condition:
- Retrieve user ID, company, and total spend.
- Only include advertisers who spent more than the average.
user_id | company | total_spent |
---|---|---|
2 | BigTech Corp | 200000 |
4 | FashionHub | 120000 |
Write an SQL query to return the requested data.