如何在 PostgreSQL 中以相反的顺序获取完整的树节点路径?
How to get full tree node path in reverse order in PostgreSQL?
我有以下table
CREATE TABLE descriptor_value (
id bigint NOT NULL,
value varchar(250),
parent_id bigint
) ;
id
列是主键。
我有三行
id | value | parent_id
----------------------
1 | foo | null
2 | bar | 1
3 | baz | 2
而且我需要创建视图以相反的顺序显示 every
节点的完整路径。例如,如果我们只考虑 baz,则必须有以下输出:
child_id | parent_id | level
----------------------------
3 | 3 | 1
3 | 2 | 2
3 | 1 | 3
谁能告诉我如何在 PgSQL 12 中做到这一点?
使用递归 CTE:
with recursive cte as (
select dv.id, dv.value, dv.parent_id, dv.parent_id as root, 1 as lev,
dv.id::text as path
from descriptor_value dv
where dv.parent_id is null
union all
select dv.id, dv.value, dv.parent_id, cte.root, lev + 1,
cte.path || '-->' || (dv.id::text)
from cte join
descriptor_value dv
on dv.parent_id = cte.id
)
select cte.id, cte.value, cte.parent_id, cte.root, lev,
max(lev) over (partition by cte.root) - lev + 1 as level
from cte
order by root, lev;
Here 是一个 db<>fiddle.
我认为您想从叶子遍历树到节点。那将是:
with recursive cte as (
select id child_id, id parent_id, 1 lvl, parent_id real_parent_id
from descriptor_value dv
where not exists (select 1 from descriptor_value dv1 where dv1.parent_id = dv.id)
union all
select c.child_id, dv.id parent_id, lvl + 1, dv.parent_id
from cte c
inner join descriptor_value dv on dv.id = c.real_parent_id
)
select child_id, parent_id, lvl from cte order by lvl
递归查询的锚点从不是任何其他节点父节点的行开始。然后我们爬上树,每一步递增 lvl
,直到到达根。
child_id | parent_id | lvl
-------: | --------: | --:
3 | 3 | 1
3 | 2 | 2
3 | 1 | 3
如果想从任意一个节点开始,那就更简单了:我们只需要改变anchor的定义即可:
with recursive cte as (
select id child_id, id parent_id, 1 lvl, parent_id real_parent_id
from descriptor_value dv
union all
select c.child_id, dv.id parent_id, lvl + 1, dv.parent_id
from cte c
inner join descriptor_value dv on dv.id = c.real_parent_id
)
select child_id, parent_id, lvl from cte order by child_id, lvl
child_id | parent_id | lvl
-------: | --------: | --:
1 | 1 | 1
2 | 2 | 1
2 | 1 | 2
3 | 3 | 1
3 | 2 | 2
3 | 1 | 3
我有以下table
CREATE TABLE descriptor_value (
id bigint NOT NULL,
value varchar(250),
parent_id bigint
) ;
id
列是主键。
我有三行
id | value | parent_id
----------------------
1 | foo | null
2 | bar | 1
3 | baz | 2
而且我需要创建视图以相反的顺序显示 every
节点的完整路径。例如,如果我们只考虑 baz,则必须有以下输出:
child_id | parent_id | level
----------------------------
3 | 3 | 1
3 | 2 | 2
3 | 1 | 3
谁能告诉我如何在 PgSQL 12 中做到这一点?
使用递归 CTE:
with recursive cte as (
select dv.id, dv.value, dv.parent_id, dv.parent_id as root, 1 as lev,
dv.id::text as path
from descriptor_value dv
where dv.parent_id is null
union all
select dv.id, dv.value, dv.parent_id, cte.root, lev + 1,
cte.path || '-->' || (dv.id::text)
from cte join
descriptor_value dv
on dv.parent_id = cte.id
)
select cte.id, cte.value, cte.parent_id, cte.root, lev,
max(lev) over (partition by cte.root) - lev + 1 as level
from cte
order by root, lev;
Here 是一个 db<>fiddle.
我认为您想从叶子遍历树到节点。那将是:
with recursive cte as (
select id child_id, id parent_id, 1 lvl, parent_id real_parent_id
from descriptor_value dv
where not exists (select 1 from descriptor_value dv1 where dv1.parent_id = dv.id)
union all
select c.child_id, dv.id parent_id, lvl + 1, dv.parent_id
from cte c
inner join descriptor_value dv on dv.id = c.real_parent_id
)
select child_id, parent_id, lvl from cte order by lvl
递归查询的锚点从不是任何其他节点父节点的行开始。然后我们爬上树,每一步递增 lvl
,直到到达根。
child_id | parent_id | lvl -------: | --------: | --: 3 | 3 | 1 3 | 2 | 2 3 | 1 | 3
如果想从任意一个节点开始,那就更简单了:我们只需要改变anchor的定义即可:
with recursive cte as (
select id child_id, id parent_id, 1 lvl, parent_id real_parent_id
from descriptor_value dv
union all
select c.child_id, dv.id parent_id, lvl + 1, dv.parent_id
from cte c
inner join descriptor_value dv on dv.id = c.real_parent_id
)
select child_id, parent_id, lvl from cte order by child_id, lvl
child_id | parent_id | lvl -------: | --------: | --: 1 | 1 | 1 2 | 2 | 1 2 | 1 | 2 3 | 3 | 1 3 | 2 | 2 3 | 1 | 3