Sql 在复杂的层次结构上使用递归
我尝试将递归用于非常复杂的层次结构,如下所示:Sql 在复杂的层次结构上使用递归,sql,postgresql,recursion,Sql,Postgresql,Recursion,我尝试将递归用于非常复杂的层次结构,如下所示: Root | Second | Third | Leaf 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
Root
|
Second
|
Third
|
Leaf
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;
但如果没有第二个,也可能是这样:
Root
|
Third
|
Leaf
我的SQL查询如下所示:
Root
|
Second
|
Third
|
Leaf
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;
下面是一个带有关系表和递归查询的SQLFIDLE链接:
问题是递归返回这个层次结构的子路径。
我只对每个层次结构的最完整路径感兴趣,在本例中,仅对以下记录感兴趣:
BB CC 2 A,BB,CC
C D 3 A,B,C,D
注意:我知道子路径对于递归是必要的,
因此,我正在寻找一种在递归之后过滤掉冗余记录的方法 在最终查询中,您只能选择没有子节点的叶子节点:
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)
在最终查询中,只能选择没有子节点的叶子节点:
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)
如果我理解正确,您希望:
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
);
如果我理解正确,您希望:
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
);
您希望返回什么结果集?您希望返回什么结果集?