SQL WITH clause example
Mastering SQL's WITH Clause: Enhancing Readability and Performance

Explore the power of SQL's WITH clause (Common Table Expressions - CTEs) to write cleaner, more modular, and often more efficient queries. This article covers basic syntax, advanced use cases, and best practices.
The SQL WITH
clause, also known as Common Table Expressions (CTEs), is a powerful feature introduced in SQL:1999 that significantly improves the readability and maintainability of complex SQL queries. It allows you to define a temporary, named result set that you can reference within a single SELECT
, INSERT
, UPDATE
, or DELETE
statement. Think of it as creating a temporary view that exists only for the duration of the query execution.
Understanding the Basics of WITH Clause
At its core, a CTE provides a way to break down complex queries into smaller, more manageable, and logical units. This modular approach makes your SQL code easier to understand, debug, and refactor. A CTE is defined using the WITH
keyword, followed by a name for the CTE, an optional list of column names, and then the defining query.
WITH SalesSummary AS (
SELECT
ProductID,
SUM(Quantity * Price) AS TotalRevenue
FROM
OrderDetails
GROUP BY
ProductID
)
SELECT
p.ProductName,
ss.TotalRevenue
FROM
Products p
JOIN
SalesSummary ss ON p.ProductID = ss.ProductID
WHERE
ss.TotalRevenue > 10000;
Basic SQL WITH clause example to summarize sales and join with product information.
flowchart TD A[Start Query] --> B{"WITH SalesSummary AS (...)"} B --> C[Define SalesSummary CTE] C --> D[Main SELECT Statement] D --> E[Join Products and SalesSummary] E --> F[Filter by TotalRevenue] F --> G[End Query]
Flowchart illustrating the execution order of a SQL query with a CTE.
Advanced Use Cases: Recursive CTEs and Multiple CTEs
The WITH
clause isn't just for simple subquery replacements. It truly shines in more advanced scenarios, such as defining recursive queries for hierarchical data (e.g., organizational charts, bill of materials) or chaining multiple CTEs together to build complex logic step-by-step. Recursive CTEs require a UNION ALL
or UNION
operator to combine an anchor member (the base case) with a recursive member (the iterative step).
WITH RECURSIVE EmployeeHierarchy AS (
-- Anchor Member: Top-level employees (no manager)
SELECT
EmployeeID,
EmployeeName,
ManagerID,
1 AS Level
FROM
Employees
WHERE
ManagerID IS NULL
UNION ALL
-- Recursive Member: Employees reporting to those in the hierarchy
SELECT
e.EmployeeID,
e.EmployeeName,
e.ManagerID,
eh.Level + 1 AS Level
FROM
Employees e
JOIN
EmployeeHierarchy eh ON e.ManagerID = eh.EmployeeID
)
SELECT
EmployeeID,
EmployeeName,
ManagerID,
Level
FROM
EmployeeHierarchy
ORDER BY
Level, EmployeeName;
Example of a recursive CTE to traverse an employee hierarchy.
WITH
block.WITH RecentOrders AS (
SELECT
OrderID, CustomerID, OrderDate
FROM
Orders
WHERE
OrderDate >= DATE('now', '-30 days')
),
CustomerOrderCount AS (
SELECT
CustomerID,
COUNT(OrderID) AS NumberOfRecentOrders
FROM
RecentOrders
GROUP BY
CustomerID
)
SELECT
c.CustomerName,
coc.NumberOfRecentOrders
FROM
Customers c
JOIN
CustomerOrderCount coc ON c.CustomerID = coc.CustomerID
WHERE
coc.NumberOfRecentOrders > 5;
Chaining multiple CTEs to find customers with more than 5 recent orders.
Benefits and Considerations
The primary benefits of using the WITH
clause include improved readability, easier debugging, and the ability to reuse complex subqueries within the same statement. While CTEs are often optimized by the database engine similarly to derived tables (subqueries in the FROM
clause), they can sometimes offer performance advantages, especially with recursive queries or when the optimizer can materialize the CTE result set. However, it's important to note that CTEs are not a magic bullet for performance; their main strength lies in code organization.