Hello! Welcome back to our course.
In our last lesson, we explored how to use subqueries in the FROM clause to create derived tables. We saw how powerful this is for multi-stage aggregations and performance optimization. However, we also got a glimpse of a major drawback: nesting derived tables can make your queries complex and difficult to read. The logic gets buried deep inside multiple layers of parentheses.
Today, we'll learn the modern and elegant solution to that problem. Our learning outcome is to rewrite a complex query using a Common Table Expression (CTE) for improved readability. A CTE is essentially a named derived table, but by defining it at the start of your query, you create a clear, logical, top-down flow that is much easier to write, debug, and maintain. This directly addresses your preference for understanding the "why" and logical structure of code.
What is a Common Table Expression (CTE)?
A Common Table Expression, or CTE, is a temporary, named result set that you can reference within a SELECT, INSERT, UPDATE, or DELETE statement. You can think of it as giving a name to a subquery's result, allowing you to use that name as if it were a regular table.
The fundamental structure is introduced with the WITH keyword.

The main motivation for using a CTE is to improve clarity. Instead of nesting logic inside a FROM clause, you define your logical steps at the top.

Let's read a short article that formally defines CTEs and their syntax.
From Chaos to Clarity: Transforming Complex SQL Queries ...
This article, 'From Chaos to Clarity' by Sagnick, gives a great introduction to what a CTE is and its basic syntax.
Read the first three sections: 'A Personal Journey to Discovering CTEs,' 'What is a Common Table Expression (CTE)?', and 'Syntax of a CTE.' Focus on the core idea that a CTE is a temporary, named result set that helps organize your code.
From Complex Subquery to Readable CTE
The best way to understand the value of CTEs is to see one in action. We'll look at a query that becomes difficult to follow using nested subqueries and then see how it can be refactored for clarity.
This is where your interest in logical, computational thinking comes into play. A complex problem can be broken down into a sequence of simpler steps. CTEs allow your SQL code to directly reflect that sequential logic.
Let's watch a video that walks through a complex business problem, first solving it with confusing nested subqueries, and then refactoring it into a clean, readable query with CTEs.
SQL WITH Clause | How to write SQL Queries using WITH Clause | SQL CTE (Common Table Expression)
This video from techTFQ provides an excellent, detailed walkthrough of refactoring a complex query.
Watch the segment from 06:25 to 20:24. First, pay attention to the problem statement: Find stores whose sales are better than the average sales across all stores. Observe the subquery-based solution (around 12:45): Notice how one subquery is nested inside another. Try to follow the logic—it's possible, but it's not straightforward. Finally, focus on the CTE-based solution (starting around 16:15): See how the logic is broken into two named steps, total_sales and average_sales. The final SELECT statement becomes simple and declarative, describing what you want to do with those steps, not how to build them.
After watching, you should see the core benefit:
- Before (Nested Subqueries): The logic is inside-out and hard to follow. To understand the query, you have to mentally unravel the nested parts first.
- After (CTEs): The logic reads from top to bottom. Each step is a named, self-contained block. This makes the query self-documenting.
A Practical Refactoring Example
Let's solidify this with another example. Complex reports are a common task in both development and technical support roles. The ability to write clean, maintainable queries is a highly valuable skill.
This article provides a fantastic, real-world example of transforming a truly messy query into a clean one using a series of CTEs.
How to Simplify Complex SQL Queries (With Examples)
This article, 'How to Simplify Complex SQL Queries' from StrataScratch, demonstrates refactoring with a practical business problem.
Read the section 'Complex SQL Queries Example #1 - Distance Per Dollar.' First, look at the initial solution with the nested subqueries. Don't worry about understanding every detail; just appreciate its complexity. Then, read the refactored solution that uses multiple CTEs (added_distance_per_dollar, added_year_month, etc.). Notice how each CTE performs one clear, logical transformation. This is the essence of writing clean SQL.
Test your understanding!
Recall the problem from our last lesson: "Find the highest total amount a single customer has spent in a single day," using the Orders table (order_id, customer_id, order_date, order_total).
The derived table solution was:
SELECT MAX(daily_customer_total) AS max_daily_spend
FROM (
SELECT customer_id, order_date, SUM(order_total) AS daily_customer_total
FROM Orders
GROUP BY customer_id, order_date
) AS customer_daily_spend;
How would you rewrite this query using a Common Table Expression?
Show answer
You would define the subquery as a CTE at the beginning of your query.
WITH customer_daily_spend AS (
-- This CTE calculates the total spent by each customer per day
SELECT
customer_id,
order_date,
SUM(order_total) AS daily_customer_total
FROM
Orders
GROUP BY
customer_id,
order_date
)
-- The main query now simply selects from the named CTE
SELECT
MAX(daily_customer_total) AS max_daily_spend
FROM
customer_daily_spend;
Notice how the logic is now read from top to bottom. First, we define what customer_daily_spend is, then we use it.
Key Advantages of CTEs
We've focused on readability, but CTEs offer several other advantages that are critical in a professional environment.
- Improved Readability and Maintainability: As we've seen, this is the primary benefit. It's easier for you to come back to your code later, and for colleagues to understand it.
- Simplified Debugging: If your query isn't working, you can run the
SELECTstatement inside each CTE independently to check its results at each stage. This is much harder with nested subqueries. - Reusability within a Query: Unlike a derived table, a CTE can be referenced multiple times in the same query. This is highly efficient. The database computes the CTE's result once and reuses it. From your systems programming background, you can think of this as calculating a value, storing it in a temporary variable, and then using that variable multiple times.
Let's watch a short video that summarizes these benefits and specifically demonstrates the reusability advantage.
SQL WITH Clause | Clearly Explained | CTEs vs Subqueries vs Temp Tables | Recursive CTEs
This segment from Maven Analytics clearly explains the advantages of CTEs, including reusability.
Watch the segment from 04:04 to 05:45. The presenter shows how a CTE named MP can be referenced twice in the main query. This is something you cannot do with a derived table. This is a key technical difference and a powerful feature for more advanced queries.
Conclusion
Today you've learned one of the most important techniques for writing professional, maintainable SQL. By moving beyond nested subqueries to Common Table Expressions, you can structure your logic in a way that is clean, modular, and easy for anyone to understand.
Key Takeaways:
- A Common Table Expression (CTE) is a temporary result set defined using the
WITHclause. - CTEs solve the readability problem of complex nested subqueries by allowing you to name logical steps and define them at the top of your query.
- The primary benefit is readability, which leads to easier maintenance and debugging.
- A key technical advantage is reusability: a CTE can be computed once and referenced multiple times within the same outer query.
Preview of the Next Lesson:
In the examples today, we saw how multiple CTEs can be used to break down a single problem. In our next lesson, we will formalize this by learning how to chain multiple CTEs, where each CTE builds upon the result of the one before it. This technique allows you to create sophisticated, multi-step data processing pipelines entirely within a single SQL query.