我有一个以下结构的表格。 p_id为null的元素将显示为根,而p_id列中提到的所有元素将显示为id,而id列中的其余元素显示为叶子。这是写查询的正确方法还是在postgres sql中有更优化的写查询方法。
select id, 'Leaf' as node
from tree
where id NOT IN ( select distinct t1.id as node
from tree t1 join tree t2 on t1.id = t2.p_id )
union
select distinct p_id, 'Inner' as node
from tree
where p_id NOT IN( select id from tree where p_id IS NULL)
union
select id, 'Root'
from tree
where p_id is NULL
order by id
相同的表格看起来像
我已经尝试了上面的查询,并且给出了预期的结果,但是,我不确定是否完美。
id p_id
-----------
1 2
3 2
6 8
9 8
2 5
8 5
5 (null)
1 Leaf
2 Inner
3 Leaf
5 Root
6 Leaf
8 Inner
9 Leaf
答案 0 :(得分:1)
通常在使用树时,会有一个单独的节点表。如果是这样,您不必为此使用union
,但可以将逻辑移到select
中:
select id,
(case when not exists (select 1 from tree t where t.id = n.id and t.p_id is null)
then 'root'
when not exists (select 1 from tree t where t.p_id = n.id)
then 'leaf'
else 'inner'
end)
from nodes n;
您也可以在没有nodes
表的情况下执行此操作:
select v.id,
(case when count(*) filter (where t.p_id is null) > 0 then 'root'
when bool_and(v.is_child) then 'leaf'
else 'inner'
end)
from tree t cross join lateral
(values (id, true), (p_id, false)
) v(id, is_child)
where v.id is not null
group by v.id
order by v.id;
Here是db <>小提琴。