Reputation: 9654
I understand conventional CTE and recursion, like shown in the below example:
-- Create an Employee table.
CREATE TABLE dbo.MyEmployees
(
EmployeeID SMALLINT NOT NULL,
FirstName NVARCHAR(30) NOT NULL,
LastName NVARCHAR(40) NOT NULL,
Title NVARCHAR(50) NOT NULL,
DeptID SMALLINT NOT NULL,
ManagerID INT NULL,
CONSTRAINT PK_EmployeeID PRIMARY KEY CLUSTERED (EmployeeID ASC)
);
-- Populate the table with values.
INSERT INTO dbo.MyEmployees VALUES
(1, N'Ken', N'Sánchez', N'Chief Executive Officer',16,NULL)
,(273, N'Brian', N'Welcker', N'Vice President of Sales',3,1)
,(274, N'Stephen', N'Jiang', N'North American Sales Manager',3,273)
,(275, N'Michael', N'Blythe', N'Sales Representative',3,274)
,(276, N'Linda', N'Mitchell', N'Sales Representative',3,274)
,(285, N'Syed', N'Abbas', N'Pacific Sales Manager',3,273)
,(286, N'Lynn', N'Tsoflias', N'Sales Representative',3,285)
,(16, N'David',N'Bradley', N'Marketing Manager', 4, 273)
,(23, N'Mary', N'Gibson', N'Marketing Specialist', 4, 16);
WITH DirectReports(ManagerID, EmployeeID, Title, EmployeeLevel) AS
(
SELECT ManagerID, EmployeeID, Title, 0 AS EmployeeLevel
FROM dbo.MyEmployees
WHERE ManagerID IS NULL
UNION ALL
SELECT e.ManagerID, e.EmployeeID, e.Title, EmployeeLevel + 1
FROM dbo.MyEmployees AS e
INNER JOIN DirectReports AS d ON e.ManagerID = d.EmployeeID
)
SELECT
ManagerID, EmployeeID, Title, EmployeeLevel
FROM
DirectReports
ORDER BY
ManagerID;
The anchor is 1 row (returns R0), and then the recursion happens that gets the employees where that row is the manager (returns R1). And then gets employees where records in R1 is manager (returns R2) and so on.. Finally UNION ALL of all these results.
I have worked out a CTE where the anchor returns more than 1 row and there is no join condition involved in the recursive query. For example the below query returns a record for all dates between start and end date - in the below query there are 2 anchors (Bob and Phil), and the UNION ALL query does not perform any join. How does such CTE work? For example - 1st it will fetch the anchor rows. Then the recursive query will return date+1 for both of the anchor row? Then the next recursive query will return date+1+1 for all the prior rows? and so on, and then finally with do a UNION ALL. I could not find an online example of such a SQL, but it works well for me, in that - it returns row for each date between the start and end dates. I am not able to visualize how recursive CTE without a JOIN actually works, any help is appreciated.
DROP TABLE IF EXISTS tempdb.dbo.#dates
CREATE TABLE #dates
(
NAME VARCHAR(50),
START DATETIME,
[END] DATETIME
)
INSERT INTO #dates
VALUES
('Bob','2014-10-30','2014-11-02'),
('Phil','2014-10-10','2014-10-15')
;WITH cte AS
(
SELECT
NAME,
[START],
[END]
FROM
#dates
UNION ALL
SELECT
NAME,
DATEADD(DAY, 1, start),
[end]
FROM
cte
WHERE
start < [END]
)
SELECT *
FROM cte
ORDER BY 1,2
Upvotes: 0
Views: 803
Reputation: 929
First of all, the anchor is not required to return only one row, it can return any size of result set. Note that SQL works on sets, not on records conceptionally.
Secondly, the requirement for the recursion is that it goes back to the CTE from the previous runs, but there is no requirement to join in external tables. And that is what you do. This recursion then continues until no more rows fulfill the second WHERE
condition.
Hence, your interpretation of how it works is correct.
Upvotes: 1