Sql 没有连接的递归CTE是如何工作的?

Sql 没有连接的递归CTE是如何工作的?,sql,sql-server,sql-server-2016,Sql,Sql Server,Sql Server 2016,我理解传统的CTE和递归,如下例所示: -- 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 SMA

我理解传统的CTE和递归,如下例所示:

-- 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;
锚定值为1,行返回R0,然后发生递归,得到该行所在的员工,经理返回R1。然后获取R1中记录为经理返回R2的员工,以此类推。。最后结合所有这些结果

我已经计算出一个CTE,其中锚返回超过1行,并且递归查询中不涉及连接条件。例如,下面的查询返回开始日期和结束日期之间所有日期的记录-在下面的查询中有2个锚Bob和Phil,而UNION all查询不执行任何联接。这种CTE是如何工作的?例如-1st它将获取锚行。然后递归查询将返回两个锚行的日期+1?然后,下一个递归查询将返回前面所有行的日期+1+1?等等,然后最后跟大家做一个联盟。我找不到这样一个SQL的在线示例,但它对我来说很好,因为它返回开始日期和结束日期之间每个日期的行。我无法想象没有连接的递归CTE是如何工作的,非常感谢您的帮助

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

首先,锚不需要只返回一行,它可以返回任意大小的结果集。请注意,SQL在集合上工作,而不是在概念上在记录上工作

其次,递归的要求是它从以前的运行返回到CTE,但不需要加入外部表。这就是你要做的。然后,此递归将继续,直到不再有行满足第二个WHERE条件


因此,您对其工作原理的解释是正确的。

无论是否使用联接,逻辑都是一样的。rCTE一直递归,直到没有返回行为止。在这种情况下,当“开始”大于或等于“结束”时。不过,如果您想为两个日期之间的每一天生成一个日期,最好使用计数;他们的表现要好得多。还有一些额外的注释。不要在ORDER BY.中使用序号位置。此外,它位于每个语句的末尾,而不是要求前一个语句正确终止的语句的开头。tally table是指包含所有日期的单列表吗?