đ A Common Table Expression (CTE) is a temporary named result set that exists only for the duration of a single SQL statement. CTEs improve the readability, organization, and maintainability of complex SQL queries by allowing you to break them into smaller, logical steps.
đ What is a Common Table Expression (CTE)?
A CTE is created using the WITH keyword, followed by a name and a query enclosed in parentheses. Once defined, the CTE behaves like a temporary table that can be referenced within the main query.
Information
đ¯ Why Use CTEs?
CTEs simplify complex queries by dividing them into smaller, reusable parts. They are especially useful for reporting, recursive queries, and improving query readability.
- đ Improve query readability.
- đ Simplify complex SQL statements.
- đ Eliminate repeated subqueries.
- đ Create recursive queries.
- đ Make SQL easier to maintain and debug.
đ Basic Syntax
CTE Syntax
WITH cte_name AS
(
SELECT column1,
column2
FROM table_name
WHERE condition
)
SELECT *
FROM cte_name;đ Sample Table
Consider the following Employees table:
| EmployeeID | EmployeeName | Department | Salary |
|---|---|---|---|
| 101 | Alice | IT | 75000 |
| 102 | Bob | HR | 55000 |
| 103 | Charlie | Finance | 68000 |
| 104 | David | IT | 82000 |
| 105 | Emma | HR | 60000 |
đĄ Basic CTE Example
Create a CTE that stores employees earning more than 70000, then retrieve the results.
Simple CTE
WITH HighSalaryEmployees AS
(
SELECT EmployeeID,
EmployeeName,
Salary
FROM Employees
WHERE Salary > 70000
)
SELECT *
FROM HighSalaryEmployees;đ CTE with Aggregate Functions
Use a CTE to calculate average salaries for each department.
Department Average Salary
WITH DepartmentAverage AS
(
SELECT Department,
AVG(Salary) AS AverageSalary
FROM Employees
GROUP BY Department
)
SELECT *
FROM DepartmentAverage;đ CTE with JOIN
CTEs can simplify queries involving joins by separating complex logic into readable steps.
CTE with JOIN
WITH EmployeeCourses AS
(
SELECT e.EmployeeName,
c.CourseName
FROM Employees e
INNER JOIN Courses c
ON e.EmployeeID = c.EmployeeID
)
SELECT *
FROM EmployeeCourses;đ Multiple CTEs
SQL allows you to define multiple CTEs in a single query. Separate each CTE with a comma.
Multiple CTEs
WITH DepartmentAverage AS
(
SELECT Department,
AVG(Salary) AS AverageSalary
FROM Employees
GROUP BY Department
),
HighSalaryEmployees AS
(
SELECT EmployeeName,
Department,
Salary
FROM Employees
WHERE Salary > 70000
)
SELECT h.EmployeeName,
h.Department,
d.AverageSalary
FROM HighSalaryEmployees h
JOIN DepartmentAverage d
ON h.Department = d.Department;đ Recursive CTE
A recursive CTE references itself and is commonly used to work with hierarchical or tree-structured data such as employee-manager relationships, organizational charts, or category hierarchies.
Recursive CTE Example
WITH RECURSIVE EmployeeHierarchy AS
(
SELECT EmployeeID,
EmployeeName,
ManagerID
FROM Employees
WHERE ManagerID IS NULL
UNION ALL
SELECT e.EmployeeID,
e.EmployeeName,
e.ManagerID
FROM Employees e
JOIN EmployeeHierarchy h
ON e.ManagerID = h.EmployeeID
)
SELECT *
FROM EmployeeHierarchy;Important
âī¸ CTE vs Subquery
| Feature | CTE | Subquery |
|---|---|---|
| Readability | Excellent for complex queries. | Can become difficult to read. |
| Reusability | Can be referenced multiple times within the same query. | Often repeated if needed multiple times. |
| Recursive Support | Yes. | No. |
| Scope | Single SQL statement. | Limited to where it is written. |
đŧ Real-World Example
A company wants to display employees whose salary is above their department's average salary.
Department Salary Analysis
WITH DepartmentAverage AS
(
SELECT Department,
AVG(Salary) AS AverageSalary
FROM Employees
GROUP BY Department
)
SELECT e.EmployeeName,
e.Department,
e.Salary,
d.AverageSalary
FROM Employees e
JOIN DepartmentAverage d
ON e.Department = d.Department
WHERE e.Salary > d.AverageSalary
ORDER BY e.Department,
e.Salary DESC;This query first calculates the average salary for each department using a CTE, then compares each employee's salary against the department average.
â ī¸ Common Mistakes
- â Forgetting the WITH keyword.
- â Trying to use a CTE outside the SQL statement where it is defined.
- â Assuming a CTE permanently stores data.
- â Omitting a termination condition in recursive CTEs, which can cause infinite recursion or recursion limit errors.
Warning
â ī¸ Best Practices
Best Practice
đ Key Points to Remember
- đ A CTE is created using the WITH keyword.
- đ It behaves like a temporary named result set.
- đ A CTE exists only for the duration of a single SQL statement.
- đ CTEs improve query readability and maintainability.
- đ Multiple CTEs can be defined in one query.
- đ Recursive CTEs are useful for hierarchical and tree-structured data.