如何为 SQL 服务器编写递归 CTE?

How to write this recursive CTE for SQL Server?

为简单起见,我的架构:

  1. 文件夹table(FolderId、ParentFolderId)

  2. DeviceFolderProperties table(FolderId、LogDataRetentionDaysEvent)

并非每个文件夹都有保留日。然而,这是一个继承的价值。你怎么能在 SQL 到 return 每个文件夹及其保留日中写一些东西,如果它是空的,它的继承值。

继承有多个层次,所以需要遍历树。

这是我试过的:

;
WITH [cte]
AS 
(
    SELECT f.FolderId, f.ParentFolderId, dfp.LogDataRetentionDaysEvent
    FROM [Folders] f
    LEFT JOIN DeviceFolderProperties dfp
    ON f.FolderId = dfp.FolderId
), 
[cte_collapse] 
AS --recurse where r days is null
(

    SELECT c.FolderId, c.ParentFolderId, c.LogDataRetentionDaysEvent
    FROM [cte] c
    WHERE c.LogDataRetentionDaysEvent IS NULL

    UNION ALL

    SELECT c.FolderId, c.ParentFolderId, ISNULL(c.LogDataRetentionDaysEvent, cc.LogDataRetentionDaysEvent)
    FROM [cte] c
    JOIN [cte_collapse] cc ON cc.FolderId = c.ParentFolderId

)
SELECT
    *
FROM 
    [cte_collapse]

你可以这样写:

with 
    data as (
        select f.FolderID, f.ParentFolderId, dfp.LogDataRetentionDaysEvent
        from Folders f
        left join DeviceFolderProperties dfp on dfp.FolderID = f.FolderID
    ),
    cte as (
        select d.*, FolderID OriginalFolderId
        from data d
        union all
        select d.*, c.OriginalFolderId
        from cte c
        inner join data d on d.FolderID = c.ParentFolderId
        where c.LogDataRetentionDaysEvent is null
    )
select OriginalFolderId, max(LogDataRetentionDaysEvent) LogDataRetentionDaysEvent
from cte 
group by OriginalFolderId

我们首先生成一个派生的 table,其中包含来自两个 table 的信息。然后,对于每条记录,递归查询向上攀登层次结构,在每个级别搜索 non-null 保留。诀窍是一遇到匹配就停止。