Reference: Programming Microsoft® SQL Server™ 2005 By Andrew J. Brust, Stephen Forte
Today I’ve gone thru the interesting recursive concepts of CTE from the book which is mentioned just above. I just want to share that concept with you all.
We will come to know the true power of CTEs, when we use them recursively to perform hierarchical queries on tree-structured data. A recursive CTE is constructed with two queries. The first, the anchor member (AM), is a non-recursive query; the second, the recursive member (RM), is the recursive query. Within your CTE's parentheses (after the AS clause), you define queries that are independent or refer back to the same CTE. The AM and RM are separated by a UNION ALL statement. AMs are invoked only once; RMs are invoked repeatedly until the query returns no rows. You can append multiple AMs to each other using a UNION or UNION ALL operator, depending on whether you want to eliminate duplicates. (You must append recursive members using a UNION ALL operator.) Here is the syntax:
WITH SimpleRecursive(field names)
AS
(
<Select Statement for the Anchor Member>
)
SELECT * FROM SimpleRecursive
The following example demonstrates this feature. We'll create a table of employees and a self-referencing field back to Employee_ID called ReportsTo. We'll then write a query that returns all the employees who report to Stephen (Employee_ID=2) and all the employees who report to Stephen's subordinates.
--create a table with tree data
CREATE TABLE Employee_Tree (Employee_NM nvarchar(50), Employee_ID int PRIMARY KEY, Repor
tsTo int)
--insert some data, build a reporting tree
INSERT INTO Employee_Tree VALUES('Richard', 1, NULL)
INSERT INTO Employee_Tree VALUES('Stephen', 2, 1)
INSERT INTO Employee_Tree VALUES('Clemens', 3, 2)
INSERT INTO Employee_Tree VALUES('Malek', 4, 2)
INSERT INTO Employee_Tree VALUES('Goksin', 5, 4)
INSERT INTO Employee_Tree VALUES('Kimberly', 6, 1)
INSERT INTO Employee_Tree VALUES('Ramesh', 7, 5)
Our table looks like this:
--Recursive Query
WITH SimpleRecursive(Employee_NM, Employee_ID, ReportsTo)
AS
(SELECT Employee_NM, Employee_ID, ReportsTo
FROM Employee_Tree WHERE Employee_ID = 2
UNION ALL
SELECT p.Employee_NM, p.Employee_ID, p.ReportsTo
FROM Employee_Tree p INNER JOIN
SimpleRecursive A ON A.Employee_ID = P.ReportsTo
)
SELECT sr.Employee_NM AS Employee, et.Employee_NM AS Boss
FROM SimpleRecursive sr INNER JOIN Employee_Tree et
ON sr.ReportsTo = et.Employee_ID
Here are the results:
Employee Boss
Stephen Richard
Clemens Stephen
Malek Stephen
Goksin Malek
Ramesh Goskin
This recursion starts where Employee_ID = 2 (the Anchor Member or the first SELECT). It picks up that record and then, using the Recursive Member (the SELECT after the UNION ALL), picks up all the records that report to Stephen and that record's children. (Goksin reports to Malek, and Malek reports to Stephen.) Each subsequent recursion tries to find more children that have as parents the employees found by the previous recursion. Eventually the recursion returns no results, and that is what causes the recursion to stop (the reason why Kimberly is not returned). If the anchor member is changed to Employee_ID = 1, then Kimberly will also be returned in the results.
No comments:
Post a Comment