【问题标题】:Issue with traversing a closure table with a CTE使用 CTE 遍历闭包表的问题
【发布时间】:2020-06-07 19:43:22
【问题描述】:

我有这个闭包表,想传递所有节点。但我在让它工作时遇到问题。这是我第一次使用 CTE,所以我真的不知道该怎么做。

这是我的relations_table

+-----+-------------+---------------+-------+------+
| id  | ancestor_id | descendant_id | depth | type |
+-----+-------------+---------------+-------+------+
| 207 |          86 |            86 |     0 |    1 |
| 208 |          87 |            87 |     0 |    1 |
| 209 |          86 |            87 |     1 |    1 |
| 210 |          88 |            88 |     0 |    1 |
| 211 |          86 |            88 |     2 |    1 |
| 212 |          87 |            88 |     1 |    1 |
| 213 |          89 |            89 |     0 |    1 |
| 214 |          87 |            89 |     1 |    1 |
| 215 |          86 |            89 |     2 |    1 |
| 216 |          90 |            90 |     0 |    1 |
| 217 |          86 |            90 |     1 |    1 |
| 218 |          91 |            91 |     0 |    1 |
| 219 |          86 |            91 |     1 |    1 |
| 220 |          92 |            92 |     0 |    1 |
| 221 |          90 |            92 |     1 |    1 |
| 222 |          86 |            92 |     2 |    1 |
| 223 |          93 |            93 |     0 |    1 |
| 224 |          90 |            93 |     1 |    1 |
| 225 |          86 |            93 |     2 |    1 |
+-----+-------------+---------------+-------+------+

我将如何编写一个查询,该查询使用 CTE 从根中传递地选择节点。我一直被这个问题困扰。

【问题讨论】:

    标签: sql-server database common-table-expression


    【解决方案1】:
    declare @t table
    (
    id  int,
    ancestor_id int,
    descendant_id int,
    depth int,
    type int
    );
    
    insert into @t(id, ancestor_id, descendant_id, depth, type)
    values
    (207 , 86 , 86 , 0 ,  1),
    (208 , 87 , 87 , 0 ,  1),
    (209 , 86 , 87 , 1 ,  1),
    (210 , 88 , 88 , 0 ,  1),
    (211 , 86 , 88 , 2 ,  1),
    (212 , 87 , 88 , 1 ,  1),
    (213 , 89 , 89 , 0 ,  1),
    (214 , 87 , 89 , 1 ,  1),
    (215 , 86 , 89 , 2 ,  1),
    (216 , 90 , 90 , 0 ,  1),
    (217 , 86 , 90 , 1 ,  1),
    (218 , 91 , 91 , 0 ,  1),
    (219 , 86 , 91 , 1 ,  1),
    (220 , 92 , 92 , 0 ,  1),
    (221 , 90 , 92 , 1 ,  1),
    (222 , 86 , 92 , 2 ,  1),
    (223 , 93 , 93 , 0 ,  1),
    (224 , 90 , 93 , 1 ,  1),
    (225 , 86 , 93 , 2 ,  1);
    
    with cte
    as
    (
        select ancestor_id as childid, cast(null as int) as parentid, ancestor_id as rootid, 0 as lvl
        from
        (
            --roots, top level parents (they are not chilren/descendants)
            select ancestor_id
            from @t
            except
            select descendant_id
            from @t
            where descendant_id <> ancestor_id
        ) as p
        union all
        select t.descendant_id, t.ancestor_id, c.rootid, c.lvl+1
        from cte as c
        join @t as t on c.childid = t.ancestor_id and t.ancestor_id <> t.descendant_id
    )
    select *
    from cte;
    
    
    --the full hierarchy of each child is logged in @t, for each parent get the list of children without cte
    select ancestor_id as parentid, stuff(c.children_concat, 1, 1, '') as children_list
    from
    (
        --parents
        select distinct ancestor_id
        from @t
    ) as p
    outer apply
    (
        select
        (
        select distinct ',' + cast(t.descendant_id as varchar(20))
        from @t as t
        where t.ancestor_id = p.ancestor_id
        and t.descendant_id <> p.ancestor_id
        order by ',' + cast(t.descendant_id as varchar(20)) --desc
        for xml path('')
        ) as children_concat
    ) as c;
    

    【讨论】:

    • 感谢您的快速帮助。我对您的第一个查询有一个问题。我有一个类似的查询,但在删除条目时遇到了问题,我将其标记为红色。有没有办法摆脱这些边缘? imgur.com/a/ea7UvVc
    • 没关系,我是通过添加带有 (relation_depth - cte_depth
    猜你喜欢
    • 2022-10-14
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    • 1970-01-01
    • 2013-07-28
    • 2016-10-01
    • 1970-01-01
    相关资源
    最近更新 更多