postgres递归视图每个插入行返回多行

postgres recursive view returning multple rows per input row

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

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

示例数据

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

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

预期输出

垂直白色-space 只是为了清楚起见。

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

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

感谢任何帮助,谢谢!

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

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

问号应替换为您要展示其 children 的组。 all_children 好像是 counter-intuitive 的列名,所以改名为 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