【问题标题】:postgres recursive view returning multple rows per input rowpostgres递归视图每个输入行返回多行
【发布时间】:2020-05-15 22:13:06
【问题描述】:

我想要一个递归视图,它报告给定组的所有孩子,每行一个。

我已经尝试了 postgres 文档中的基本示例,并进行了修改以尝试在每个递归步骤中返回多行,但我一直以无限循环结束。

样本数据

create table groups (
       group_id varchar,
       parent_id varchar
       );

insert into groups (group_id, parent_id) values
       ('A',NULL),
       ('B','A'),
       ('C','B'),
       ('D','C'),
       ('E','A')
       ;

--      A
--    /   \
--   E     B
--          \
--           C
--            \
--             D

select * from groups;

group_id |parent_id 
---------|----------
A        |[NULL]    
B        |A         
C        |B         
D        |C
E        |A

我想要一个递归视图,它报告给定组的每个孩子,每行一个。

预期输出

垂直空白只是为了清晰。

select * from group_recursive;

group_id | parent_id | all_children_ids
---------|-----------|-----------------
A        | NULL      | A        

B        | A         | B
B        | A         | A

E        | A         | E
E        | A         | A

C        | B         | C
C        | B         | B
C        | B         | A

D        | C         | D
D        | C         | C
D        | C         | B
D        | C         | A

select * from group_recursive where all_children_ids = 'A';
A        | NULL      | A
B        | A         | A
E        | A         | A
C        | B         | A
D        | C         | A

select * from group_recursive where all_children_ids = 'B';
B        | A         | B
C        | B         | B
D        | C         | B

select * from group_recursive where all_children_ids = 'D';
D        | C         | D

我不得不假设这是一个可能的视图,但如果有必要我可以更改为定义一个函数或其他东西。

感谢任何帮助,谢谢!

【问题讨论】:

    标签: sql postgresql select common-table-expression recursive-query


    【解决方案1】:

    您可以使用以下查询获取给定组的所有子项:

    with recursive cte as (
        select group_id, parent_id, group_id root_id, 0 lvl from groups where group_id = ?
        union all
        select g.group_id, g.parent_id, c.root_id, c.lvl + 1
        from groups g
        inner join cte c on c.group_id = g.parent_id
    )
    select * from cte order by lvl, group_id
    

    问号应替换为您要展示其孩子的组。 all_children 似乎是一个违反直觉的列名,所以我将其重命名为 root_id。作为奖励,我添加了一个名为 lvl 的列,表示每个组相对于根的深度。

    另一方面,如果您想生成从给定节点向上的所有路径,如您的第一个结果集中所示,您可以向上遍历树:

    with recursive cte as (
        select group_id, parent_id, group_id root_id, 0 lvl from groups
        union all
        select g.group_id, g.parent_id, c.root_id, c.lvl + 1
        from groups g
        inner join cte c on c.group_id = g.parent_id
    )
    select group_id, parent_id, root_id from cte order by group_id, parent_id, lvl
    

    Demo on DB Fiddle

    【讨论】:

    • 这正是我需要理解的,谢谢@GMB。我快到了;我还没有弄清楚group_id root_id - 这是必要的。这是我完成的视图(修剪掉lvl; 和损坏的格式,我无法弄清楚cmets 中的代码粘贴)。非常感谢。 CREATE RECURSIVE VIEW cte_view (group_id, parent_id, root_id) AS ( select group_id, parent_id, group_id root_id from groups union all select g.group_id, g.parent_id, c.root_id from groups g inner join cte_view c on c.group_id = g.parent_id ) select * from cte_view order by group_id, parent_id;
    • 我同意 - root_id 是一个比 all_children_ids 更合理的列名
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    • 2019-12-19
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多