我试图将递归用于看起来像这样的非常复杂的层次结构:
Root
|
Second
|
Third
|
Leaf
但是也可以像这样(没有第二个):
Root
|
Third
|
Leaf
我的SQL查询如下:
with recursive relations as
(select parent_id, child_id, 1 as h_level, array[parent_id,child_id] as fullpath
from public.entity_relations where parent_type = 4
union all
select c.parent_id, c.child_id, p.h_level+1, p.fullpath || c.child_id
from public.entity_relations c join relations p on p.child_id = c.parent_id)
select * from relations;
以下是带有关系表和递归查询的sqlfiddle链接:
http://sqlfiddle.com/#!17/31793/1/0
问题在于递归返回此层次结构的子路径。
我只对每个层次结构的最完整路径感兴趣,在此示例中,仅对以下记录感兴趣:
BB CC 2 A,BB,CC
C D 3 A,B,C,D
注意:我知道递归需要“子路径”, 所以我正在寻找一种在递归后过滤掉多余记录的方法。
答案 0 :(得分:2)
在最终查询中,您只能选择叶子(没有孩子的节点):
with recursive relations as (
select
parent_id,
child_id,
1 as h_level,
array[parent_id,child_id] as fullpath
from entity_relations where parent_type = 4
union all
select
c.parent_id,
c.child_id,
p.h_level+1,
p.fullpath || c.child_id
from entity_relations c
join relations p on p.child_id = c.parent_id
)
select *
from relations r
where not exists (
select from entity_relations e
where e.parent_id = r.child_id
)
parent_id | child_id | h_level | fullpath
-----------+----------+---------+-----------
C | D | 2 | {A,C,D}
BB | CC | 2 | {A,BB,CC}
C | D | 3 | {A,B,C,D}
(3 rows)
事实证明,有两条路径通向叶子D
。您可以根据级别选择其中一种。
...
select distinct on (child_id) *
from relations r
where not exists (
select from entity_relations e
where e.parent_id = r.child_id
)
order by child_id, h_level desc
parent_id | child_id | h_level | fullpath
-----------+----------+---------+-----------
BB | CC | 2 | {A,BB,CC}
C | D | 3 | {A,B,C,D}
(2 rows)
答案 1 :(得分:1)
如果我理解正确,那么您想要:
with recursive relations as (
select parent_id, child_id, 1 as h_level, array[parent_id,child_id] as fullpath
from public.entity_relations
where parent_type = 4
union all
select c.parent_id, c.child_id, p.h_level+1, p.fullpath || c.child_id
from public.entity_relations c join
relations p
on p.child_id = c.parent_id
)
select r.*
from relations r
where not exists (select 1
from relations r2
where r2.fullpath @> r.fullpath and
r2.fullpath <> r.fullpath
);