选择层次结构中的所有子级

Riy*_*lly 2 sql-server-2005 sql-server recursive

我有一个像这样的分层数据表:

BookGroupID  GroupName  ParentGroupID
-----------  ---------  -------------
0            Primary    0
1            abc        0
2            abd        0
3            abe        0
4            cbc        1
5            ceg        2
6            cjd        3
7            hjd        5
8            bjy        5
9            mfs        4
10           ikl        7
11           hjy        8
12           mnf        5
13           aws        10
14           qws        11
15           aqe        13
Run Code Online (Sandbox Code Playgroud)

我想在层次结构中选择一个特定的 BookGroupID 及其所有直接和间接子级。例如,对于 2 的 BookGroupID,输出应如下所示:

BookGroupID
-----------
2
5
7
8
10
11
12
13
14
15
Run Code Online (Sandbox Code Playgroud)

解释一下,第 5 行在输出中,因为它是第 2 行的直接孩子,第 7、8 和 12 行是第 5 行的直接孩子,第 15 行是第 13 行的孩子,这是第 10 行的孩子,也是第 7 行的孩子, 14 是 11 的孩子,是 8 的孩子。

那么,我怎样才能在 SQL 中做到这一点呢?

Liy*_*sky 6

要使用的技术称为递归公用表表达式或递归 CTE。Microsoft SQL 文档很全面,有很多第三方博客文章可以帮助解释。

这是您的特定问题的实现。

这部分只是从您的问题中创建示例数据。它使用临时表(使用# 符号的表)

    create table #t (BookGroupID int, GroupName varchar(100), ParentGroupID int)
    insert into #t 
    values 
    (0      ,'Primary',    0    ),
    (1      ,'abc',        0    ),
    (2      ,'abd',        0    ),
    (3      ,'abe',        0    ),
    (4      ,'cbc',        1    ),
    (5      ,'ceg',        2    ),
    (6      ,'cjd',        3    ),
    (7      ,'hjd',        5    ),
    (8      ,'bjy',        5    ),
    (9      ,'mfs',        4    ),
    (10     ,'ikl',        7    ),
    (11     ,'hjy',        8    ),
    (12     ,'mnf',        5    ),
    (13     ,'aws',        10),
    (14     ,'qws',        11),
    (15     ,'aqe',        13);
Run Code Online (Sandbox Code Playgroud)

这是开始寻找的价值:

    declare @parent int = 2;
Run Code Online (Sandbox Code Playgroud)

这就是递归 CTE。您不必像本例中那样将其称为“cte”。最初的分号是多余的。如果程序员懒惰,它可以确保上一条语句正确结束。离开它没有坏处。

    ;with cte 
    as (select BookGroupId
        from #t as t 
        where BookGroupId = @parent
        UNION ALL
        select t.BookGroupId
        from #t as t 
        join cte 
        on t.ParentGroupId = cte.BookGroupId)
    select *
    from cte
    order by BookGroupId;
Run Code Online (Sandbox Code Playgroud)