Select node/descendant 对用于树层次结构中的每个排列

Select node/descendant pairs for every permutation in tree hierarchy

我有一个文件夹树结构表示在 SQL 服务器 table:

Id  ParentId
------------
1   NULL
2   1
3   1
4   2
5   3

我想构建一个 SQL 查询以提供 文件夹 ID 到后代文件夹 ID 的所有排列

FolderId  DescendantFolderId
----------------------------
1         2
1         3
1         4
1         5
2         4
3         5

到目前为止,我已经编写了以下查询,但它只是 select 直接相关的 node/child 对:

WITH
    RecursiveFolders
AS
(
    SELECT 
        [Id], 
        [ParentId]
    FROM
        [Folders]
    WHERE
        [ParentId] is NULL

    UNION ALL

    SELECT    
        f.[Id],
        f.[ParentId]
    FROM    
        [Folders] f
        INNER JOIN
            RecursiveFolders r
        ON
            r.Id = f.ParentId
)
SELECT DISTINCT
    [ParentId] as FolderId,
    [Id] as DescendantFolderId
FROM
    RecursiveFolders
WHERE
    [ParentId] is not NULL
ORDER BY
    [ParentId],
    [Id]

输出:

FolderId  DescendantFolderId
----------------------------
1         2
1         3
2         4
3         5

如何 select 文件夹到后代文件夹的所有排列?

您可以在 CROSS APPLY 中将数据类型 hierarchyIDIsDescendantOf() 一起使用...也可以是自我 JOIN

示例或dbFiddle

;with cte as (
      Select ID
            ,ParentId 
            ,HierID = convert(hierarchyid,concat('/',ID,'/'))
      From   Folders 
      Where  ParentId is null
      Union  All
      Select ID  = r.ID
            ,ParentId  = r.ParentId 
            ,HierID = convert(hierarchyid,concat(p.HierID.ToString(),r.ID,'/'))
      From   Folders r
      Join   cte p on r.ParentId  = p.ID
)
Select FolderID = A.ID
      ,DescendantFolderId = B.ID
 From  cte A
 Cross Apply (
               Select *
                 From cte 
                Where HierID.IsDescendantOf( A.HierID ) = 1
             ) B
 Where A.ID<>B.ID
 Order By A.HierID

结果

FolderID    DescendantFolderId
1           2
1           3
1           5
1           4
2           4
3           5