Open In App

CTE in SQL

Last Updated : 15 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

In SQL, a Common Table Expression (CTE) is an essential tool for simplifying complex queries and making them more readable. By defining temporary result sets that can be referenced multiple times, a CTE in SQL allows developers to break down complicated logic into manageable parts. CTEs help with hierarchical data representation, improve code reusability, and simplify maintenance.

In this article, we will explain SQL CTEs, their purpose, syntax, and practical applications with examples. We will also explore recursive CTEs, their structure, and when to use them. By the end, we will know to use the CTEs in SQL queries for better performance and readability.

Why CTEs Are Important in SQL

A Common Table Expression (CTE) in SQL is a temporary result set that is defined and used within the execution scope of a SELECT, INSERT, UPDATE, or DELETE statement. CTEs are defined using the WITH clause and can be referenced multiple times within the main SQL query. This makes CTEs a great alternative to subqueries, especially in cases where we need to perform the same operation multiple times or create recursive queries.

Why Use CTEs in SQL?

CTEs simplify query writing and maintenance by:

  • Breaking down complex queries into smaller, reusable components.
  • Improving readability and modularity by separating the logic.
  • Enabling recursive operations for hierarchical data.

Syntax

WITH cte_name AS (
SELECT query
)
SELECT *
FROM cte_name;

Key Terms

  • cte_name: A unique name for the CTE expression.
  • query: A valid SQL query that returns a result set, which will be treated as a virtual table within the main query.
  • SELECT: The main query that can reference the CTE by its name.

Creating a Simple CTE in SQL

Let’s consider an Employees table that contains employee details such as EmployeeID, Name, Department, Salary, and ManagerID. This table is used to demonstrate how to use a Common Table Expression (CTE) to simplify SQL queries, particularly when aggregating or filtering data.

Employees-Table
Employees table

Example: Calculate Average Salary by Department

In this example, we will use a Common Table Expression (CTE) to calculate the average salary for each department in the Employees table. The CTE simplifies the query by breaking it into a manageable part that can be referenced in the main query.

Query:

WITH AvgSalaryByDept AS (
SELECT Department, AVG(Salary) AS AvgSalary
FROM Employees
GROUP BY Department
)
SELECT *
FROM AvgSalaryByDept;

Output

DepartmentAvgSalary
IT75000
HR60000
Finance52500

Explanation:

  • The WITH clause defines a CTE named AvgSalaryByDept.
  • The main query references this CTE to retrieve the average salary for each department.

Recursive Common Table Expression 

A recursive CTE is one that references itself within that CTE. The recursive CTE is useful when working with hierarchical data as the CTE continues to execute until the query returns the entire hierarchy. A typical example of hierarchical data is a table that includes a list of employees. For every employee, the table provides a reference to that person’s manager.

That reference is itself an employee ID within the same table. We can use a recursive CTE to display the hierarchy of employee data. If a CTE is created incorrectly it can enter an infinite loop. To prevent this, the MAXRECURSION hint can be added in the OPTION clause of the primary SELECT, INSERT, UPDATE, DELETE, or MERGE statement.

Recursive CTEs consist of two parts:

  1. Anchor member: The initial query that selects the base case (e.g., top-level managers).
  2. Recursive member: The query that references the CTE itself, pulling the next level of data.

Example: Hierarchical Employee Data

WITH
cteReports (EmpID, FirstName, LastName, MgrID, EmpLevel)
AS
(
SELECT EmployeeID, FirstName, LastName, ManagerID, 1
FROM Employees
WHERE ManagerID IS NULL
UNION ALL
SELECT e.EmployeeID, e.FirstName, e.LastName, e.ManagerID,
r.EmpLevel + 1
FROM Employees e
INNER JOIN cteReports r
ON e.ManagerID = r.EmpID
)

SELECT
FirstName + ' ' + LastName AS FullName,
EmpLevel,
(SELECT FirstName + ' ' + LastName FROM Employees
WHERE EmployeeID = cteReports.MgrID) AS Manager
FROM cteReports
ORDER BY EmpLevel, MgrID

Output

NameLevel
John Smith1
Jane Doe2
Alice Brown2
Bob Green3
Charlie Ray3

Explanation:

  • The anchor member selects employees with no manager (ManagerID IS NULL), establishing the base level.
  • The recursive member joins the CTE to the table, incrementing the level for each subordinate employee.

Managing Recursion with MAXRECURSION

To avoid infinite recursion, SQL Server imposes a recursion limit. By default, the recursion depth is set to 100, but you can customize this using the MAXRECURSION hint:

OPTION(MAXRECURSION 50);

This limits the recursion to 50 levels. If the recursion exceeds this limit, SQL Server will stop and return an error.

Benefits of Using CTEs in SQL

  1. Improved Readability: CTEs help break down complex queries into modular, reusable components, improving code readability and maintainability.
  2. Reusability: Once defined, a CTE can be referenced multiple times within the same query, reducing the need for repetitive code.
  3. Simplifies Complex Queries: By using CTEs, especially recursive CTEs, complex operations like hierarchical data queries become much easier to manage.
  4. Query Optimization: SQL engines can optimize queries that use CTEs more efficiently, improving performance, especially when the same result set needs to be accessed multiple times.

Limitations of CTEs in SQL

  • Temporary Scope: A CTE exists only during the execution of the query. Once the query completes, the CTE is discarded.
  • Performance Issues: For very large datasets, CTEs can sometimes lead to performance degradation due to multiple references to the same CTE.
  • Not Allowed in All Database Operations: Some operations, such as INSERT and UPDATE, may have restrictions when using CTEs in certain databases.

CTE vs Subqueries

FeatureCTESubquery
ReusabilityCan be referenced multiple times.Typically used once.
ReadabilityImproves readability for complex queries.Can become difficult to read when nested.
PerformanceOptimized for multiple references.May be less efficient for repeated operations.

Conclusion

In summary, Common Table Expressions (CTEs) are a valuable feature in SQL, enhancing query readability, modularity, and performance. By using CTEs, developers can simplify complex queries, especially those involving hierarchical data or repeated subqueries. Whether we’re using CTEs in SQL Server, PostgreSQL, or Azure, understanding how to define and use them effectively will empower us to write cleaner, more efficient SQL queries.


Next Article
Article Tags :

Similar Reads