Specifies a temporary named result set, known as a common table expression (CTE). It is commonly used for recursion when a function calls itself multiple times & make queries and subqueries more readable.
;WITH deptCTE (id, department, parent) AS
SELECT id, department, parent
SELECT q1.department, q2.department
FROM (SELECT id, department, parent
INNER JOIN (SELECT id, department, parent
;WITH deptCTE(id, department, parent) AS
(SELECT id, department, parent
SELECT q1.department, q2.department
INNER JOIN deptCTE q2 on q1.id = q2.parent
It is recursive when the CTE references itself
SELECT 1 + N FROM Numbers
Recursion stops when the second SELECT produces no results
Specify MAXRECURSION: Default is 100 & MAXRECURSION of 0 implies no maximum
Uses: Hierarchical listing of categories & Recursive calculations
;WITH DepartmentCTE(DeptId, Department, Parent, Level) AS
( SELECT id as DeptId, Department, parent, 0 as Level
/***** and now for the recursive part *****/
SELECT d.id as DeptId, d.Department, d.parent,
DepartmentCTE.Level + 1 as Level
ON DepartmentCTE.DeptId = d.parent)
/*****Specify MAXRECURSION*****/
You can use in multiple ways for formatting the hierarchy
--Recursive CTE with Tree Path
;WITH DepartmentCTE(DeptId, Department, Parent, Level, TreePath) AS
(SELECT id as DeptId, Department, Parent, 0 as Level,
cast(Department as varchar(1024)) as TreePath
UNION ALL -- and now for the recursive part
SELECT d.id as DeptId, d.Department, d.parent,
DepartmentCTE.Level + 1 as Level,
cast(DepartmentCTE.TreePath + ' -> ' +
cast(d.department as varchar(1024))
as varchar(1024)) as TreePath
ON DepartmentCTE.DeptId = d.parent)
--Recursive CTE with Indentation
;WITH DepartmentCTE(DeptId, Department, Parent, Level, TreePath) AS
( SELECT id as DeptId, Department, parent, 0 as Level,
cast(Department as varchar(1024)) as TreePath
UNION ALL -- and now for the recursive part
SELECT d.id as DeptId, d.Department, d.parent,
DepartmentCTE.Level + 1 as Level,
cast(DepartmentCTE.TreePath + ' -> ' +
cast(d.department as varchar(1024))
as varchar(1024)) as TreePath
ON DepartmentCTE.DeptId = d.parent)
SELECT REPLICATE('. ', Level) + Department
Recursive CTE is improve the performance, but using a CTE for re-use of a subquery does not improve performance.
To understand the breaks down execution refer this example, I took this from Stackoverflow site.
INSERT INTO tbl( Id, Name, ParentId )
SELECT id, Name, ParentID,
CAST(Name AS VARCHAR(1000)) AS Path
SELECT t.id, t.Name, t.ParentID,
CAST((a.path + '/' + t.Name) AS VARCHAR(1000)) AS "Path"
SELECT * FROM abcd OPTION (MAXRECURSION 1000);
The anchor statement is executed. This gives you a set of results, called the base set, or T0.
The recursive statement is executed, using T0 as the table to execute the query against. This happens automatically when you query a CTE.
If the recursive member returns some results, it creates a new set, T1. The recursive member is then executed again, using T1 as input, creating T2 if there are any results.
Step 3 continues until no more results are generated, OR the maximum number of recursions has been met, as set by the MAX_RECURSION option.
Another real common real world example is here, let’s say you have to find the master application_id for the current application_id.
To understand recursion, I have added additional columns as recursion. The recursion will end when the second query does not return any value.