postgres递归视图,每输入一行返回多个行

问题描述 投票:1回答:1

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

我已经尝试了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         | A
C        | B         | A
D        | C         | A

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

我必须假设这是一个视图,但如有必要,我可以更改为定义函数或其他内容。

感谢您的任何帮助,谢谢!

postgresql common-table-expression recursive-query
1个回答
0
投票

您可以通过以下查询获取给定组的所有子级:

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

© www.soinside.com 2019 - 2024. All rights reserved.