在 PostgreSQL 中是否有等效的 connect by 来按树向上移动?
Is there an equivalent of connectby in PostrgreSQL to go up by tree?
我正在学习如何在 postgresql12 中使用树并找到了一个很好的函数 connectby
。
例如:
SELECT * FROM connectby('descriptor_value', 'descriptor_value_id',
'parent_value_id', '1', 0, '->')
给出以下输出:
但是,我不想从根开始构建所有树,我想从节点(性能)开始得到分支到根。例如,我想作为参数 87
传递并得到 1->86->87
。有没有这个功能?
这通常是使用 recursive common table expression 完成的。
with recursive cte as (
select descriptor_value_id, parent_value_id, 1 as level
from descriptor_value
where descriptor_value_id = 87
union all
select p.descriptor_value_id, p.parent_value_id, c.level + 1
from descriptor_value p
join cte c on c.parent_value_id = p.descriptor_value_id
)
select *
from cte;
自从在 Postgres 8.4 中引入递归 CTE 以来,connectby()
函数几乎已过时
我想你想要:
with recursive cte as (
select descriptor_value_id, parent_value_id, 1 lvl
from descriptor_value
where descriptor_value_id = 87
union all
select dv.descriptor_value_id, dv.parent_value_id, lvl + 1
from descriptor_value dv
inner join cte c on c.parent_value_id = dv.descriptor_value_id
)
select string_agg(descriptor_value_id::text, '->' order by lvl desc) full_path from cte
递归查询从给定的 descriptor_value_id
开始向上爬树。然后,外部查询通过以相反的顺序聚合找到的 ID 来生成完整路径。
这会为您提供单行单列的结果,其中包含给定节点的完整路径。
可以通过修改递归查询锚点的where
子句来改变起始节点。
如果想用同样的逻辑一次得到每个节点的路径,还是向上遍历树,可以这样做:
with recursive cte as (
select descriptor_value_id starting_id, descriptor_value_id, parent_value_id, 1 lvl
from descriptor_value
union all
select c.starting_id, dv.descriptor_value_id, dv.parent_value_id, lvl + 1
from descriptor_value dv
inner join cte c on c.parent_value_id = dv.descriptor_value_id
)
select
starting_id,
string_agg(descriptor_value_id::text, '->' order by lvl desc) full_path
from cte
group by starting_id
然而,在那种情况下,向下走树可能更简单、更有效。
您可以交换参数 keyid_fld 和 parent_keyid_fld:
SELECT * FROM connectby('descriptor_value', 'parent_value_id', 'descriptor_value_id', '87', 0, '->')
哪个应该让你
87
87->86
87->86->1
我正在学习如何在 postgresql12 中使用树并找到了一个很好的函数 connectby
。
例如:
SELECT * FROM connectby('descriptor_value', 'descriptor_value_id',
'parent_value_id', '1', 0, '->')
给出以下输出:
但是,我不想从根开始构建所有树,我想从节点(性能)开始得到分支到根。例如,我想作为参数 87
传递并得到 1->86->87
。有没有这个功能?
这通常是使用 recursive common table expression 完成的。
with recursive cte as (
select descriptor_value_id, parent_value_id, 1 as level
from descriptor_value
where descriptor_value_id = 87
union all
select p.descriptor_value_id, p.parent_value_id, c.level + 1
from descriptor_value p
join cte c on c.parent_value_id = p.descriptor_value_id
)
select *
from cte;
自从在 Postgres 8.4 中引入递归 CTE 以来,connectby()
函数几乎已过时
我想你想要:
with recursive cte as (
select descriptor_value_id, parent_value_id, 1 lvl
from descriptor_value
where descriptor_value_id = 87
union all
select dv.descriptor_value_id, dv.parent_value_id, lvl + 1
from descriptor_value dv
inner join cte c on c.parent_value_id = dv.descriptor_value_id
)
select string_agg(descriptor_value_id::text, '->' order by lvl desc) full_path from cte
递归查询从给定的 descriptor_value_id
开始向上爬树。然后,外部查询通过以相反的顺序聚合找到的 ID 来生成完整路径。
这会为您提供单行单列的结果,其中包含给定节点的完整路径。
可以通过修改递归查询锚点的where
子句来改变起始节点。
如果想用同样的逻辑一次得到每个节点的路径,还是向上遍历树,可以这样做:
with recursive cte as (
select descriptor_value_id starting_id, descriptor_value_id, parent_value_id, 1 lvl
from descriptor_value
union all
select c.starting_id, dv.descriptor_value_id, dv.parent_value_id, lvl + 1
from descriptor_value dv
inner join cte c on c.parent_value_id = dv.descriptor_value_id
)
select
starting_id,
string_agg(descriptor_value_id::text, '->' order by lvl desc) full_path
from cte
group by starting_id
然而,在那种情况下,向下走树可能更简单、更有效。
您可以交换参数 keyid_fld 和 parent_keyid_fld:
SELECT * FROM connectby('descriptor_value', 'parent_value_id', 'descriptor_value_id', '87', 0, '->')
哪个应该让你
87
87->86
87->86->1