A common table expression (CTE) can be thought of as a temporary result set defined within the execution scope of a single SELECT, INSERT, UPDATE, DELETE, or CREATE VIEW statement.
Pseudocode and semantics
The recursive CTE structure must contain at least-
one anchor member
The first invocation of the recursive CTE consists of one ( or more) CTE_query_definition(s). Because these query definitions form the base result set of the CTE structure, they are referred to as anchor members. 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. -
one recursive member.
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.
WITH cte_name ( column_name [,...n] ) AS ( CTE_query_definition –- Anchor member is defined. UNION ALL CTE_query_definition –- Recursive member is defined referencing cte_name. ) -- Statement using the CTE SELECT * FROM cte_nameExample
We have the following data in our Category table:
CategoryID | Name | ParentID |
1 | Office | NULL |
2 | Computer | NULL |
3 | Books | NULL |
4 | Office Accessories | 1 |
5 | Furniture | 1 |
6 | Decoration Items | 1 |
7 | LCDs | 2 |
8 | CPUs | 2 |
9 | Keyboards | 2 |
10 | Urdu | 3 |
11 | Programming | 3 |
12 | ASP.Net | 11 |
13 | C# | 11 |
14 | VB.Net | 11 |
15 | Java | 11 |
16 | PHP | 11 |
17 | Poetry | 10 |
18 | Stories | 10 |
19 | Novels | 10 |
20 | Kids | 18 |
21 | Funny | 18 |
WITH CategoryList AS ( -- Anchor Query Member SELECT parent.CategoryID, CONVERT(VARCHAR(50), Parent.Name) as Name, parent.ParentID FROM Category as parent WHERE parent.ParentID IS NULL UNION ALL -- Recursive Query Member SELECT child.CategoryID, CONVERT(VARCHAR(50), CL.Name + ' > ' + child.Name) as Name, child.ParentID FROM Category as child INNER JOIN CategoryList as CL ON child.ParentID = CL.CategoryID -- Can be think of as the termination condition WHERE child.ParentID IS NOT NULL ) SELECT * FROM CategoryListThat's simple, you will get the required output as:
CategoryID | Name | ParentID |
1 | Office | NULL |
2 | Computer | NULL |
3 | Books | NULL |
10 | Books > Urdu | 3 |
11 | Books > Programming | 3 |
12 | Books > Programming > ASP.Net | 11 |
13 | Books > Programming > C# | 11 |
14 | Books > Programming > VB.Net | 11 |
15 | Books > Programming > Java | 11 |
16 | Books > Programming > PHP | 11 |
17 | Books > Urdu > Poetry | 10 |
18 | Books > Urdu > Stories | 10 |
19 | Books > Urdu > Novels | 10 |
20 | Books > Urdu > Stories > Kids | 18 |
21 | Books > Urdu > Stories > Funny | 18 |
7 | Computer > LCDs | 2 |
8 | Computer > CPUs | 2 |
9 | Computer > Keyboards | 2 |
4 | Office > Office Accessories | 1 |
5 | Office > Furniture | 1 |
6 | Office > Decoration Items | 1 |