并选择

时间:2019-04-25 08:18:28

标签: sql postgresql

我有一个以下结构的表格。 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

1 个答案:

答案 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 <>小提琴。