Open In App

CTE in SQL

Last Updated : 27 Jun, 2025
Summarize
Comments
Improve
Suggest changes
Share
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.

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.

Employee_Table
Employees Table

This table represents the hierarchical structure of employees within an organization, based on a recursive Common Table Expression (CTE) query. The table displays employees, their respective levels in the hierarchy, and the managers who supervise them.

FullNameEmpLevelManager
John Smith1NULL
Jane Doe2John Smith
Alice Brown2John Smith
Bob Green3Jane Doe
Charlie Ray3Jane Doe

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

FullNameEmpLevelManager
John Smith1NULL
Jane Doe2John Smith
Alice Brown2John Smith
Bob Green3Jane Doe
Charlie Ray3Jane Doe

Explanation:

  • John Smith is at level 1 and has no manager (Top-level employee).
  • Jane Doe and Alice Brown are at level 2, reporting to John Smith.
  • Bob Green and Charlie Ray are at level 3, reporting to Jane Doe.

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