Recursive queries using CTE like the one above usually consist of two parts within the definition of CTE. The first one gets the record(s) that you will start recursion from (anchor records)
SELECT empid, mgrid, firstname, lastname
FROM HR.Employees
WHERE empid = 2
This will select your top-most employee.
Then to achieve recursion you need to UNION
with the second part of the CTE query (to get recursive records):
UNION ALL
SELECT C.empid, C.mgrid, C.firstname, C.lastname
FROM EmpsCTE AS P
JOIN HR.Employees AS C
ON C.mgrid = P.empid
The most important points here are:
- you need to join the alias used in CTE definition (
EmpsCTE
) with the source table (HR.Employees
). This will produce recursion as it will join the records already existing in CTE with the records from the source table. This will be done until the invocation of the recurive part returns no records. - as your join condition links an employee to its manager, the recursive part will continue to produce records as long as there are new employees that work under those who the query already returned in previous iterations.
Let me also paste a section from enter link description here on that topic to explain it in the official way:
The structure of the recursive CTE in Transact-SQL is similar to recursive routines in other programming languages. Although a recursive routine in other languages returns a scalar value, a recursive CTE can return multiple rows.
A recursive CTE consists of three elements:
- Invocation of the routine.
The first invocation of the recursive CTE consists of one or more CTE_query_definitions joined by UNION ALL, UNION, EXCEPT, or INTERSECT operators. Because these query definitions form the base result set of the CTE structure, they are referred to as anchor members. CTE_query_definitions are considered anchor members unless they reference the CTE itself. All anchor-member query definitions must be positioned before the first recursive member definition, and a UNION ALL operator must be used to join the last anchor member with the first recursive member.
- Recursive invocation of the routine.
The recursive invocation includes one or more CTE_query_definitions joined by UNION ALL operators that reference the CTE itself. These query definitions are referred to as recursive members.
- Termination check.
The termination check is implicit; recursion stops when no rows are returned from the previous invocation.