如何在引用自身的postgresql表中递归地获取从给定id开始的所有id? >标题可能不太清楚,所以让我们考虑这个例子,这不是我的代码,只是用这个例子来模拟我的请求
我有一个像文件系统一样引用自身的表如何在引用自身的postgresql表中递归地获取从给定id开始的所有id? >标题可能不太清楚,所以让我们考虑这个例子,这不是我的代码,只是用这个例子来模拟我的请求,postgresql,hierarchical-data,recursive-query,Postgresql,Hierarchical Data,Recursive Query,我有一个像文件系统一样引用自身的表 id | parent | name ----+----------+------- 1 | null | / 2 | 1 | home 3 | 2 | user 4 | 3 | bin 5 | 1 | usr 6 | 5 | local 如果我选择以下选项,是否可以发出sql请求: 1我将得到一个包含2,3,4,5,6的表,因为这是匹配
id | parent | name
----+----------+-------
1 | null | /
2 | 1 | home
3 | 2 | user
4 | 3 | bin
5 | 1 | usr
6 | 5 | local
如果我选择以下选项,是否可以发出sql请求:
1我将得到一个包含2,3,4,5,6的表,因为这是匹配的根:
/家
/家庭/用户
/主页/用户/bin
/usr
等
2我将得到一个包含3,4的表,以便匹配:
/家庭/用户
/主页/用户/bin
等等使用。始终从根开始,在WHERE子句中使用id数组获取给定id的路径
对于id=1:
双向查询
这个问题真的很有趣。上面的查询工作得很好,但效率很低,因为它解析所有树节点,即使在我们请求一个叶子时也是如此。更强大的解决方案是双向递归查询。内部查询从给定节点移动到顶部,而外部查询从节点移动到底部
with recursive outer_query(id, parent, name) as (
with recursive inner_query(qid, id, parent, name) as (
select id, id, parent, name
from my_table
where id = 2 -- parameter
union all
select qid, t.id, t.parent, concat(t.name, '/', q.name)
from inner_query q
join my_table t on q.parent = t.id
)
select qid, null::int, right(name, -1)
from inner_query
where parent is null
union all
select t.id, t.parent, concat(q.name, '/', t.name)
from outer_query q
join my_table t on q.id = t.parent
)
select id, name
from outer_query
where id <> 2; -- parameter
谢谢,但我只希望在新的表格argh中返回给定目录中所有目录和子目录的id。。我不是这个意思。这更像是我需要使用其中的id=1,我将得到一个包含这5个值的表,或者如果我使用其中的id=2,我将得到一个包含这2个值的表。你明白了吗?好的,你必须使用一个额外的数组,就像更新后的答案一样。为什么不把where id=2放在最上面的查询中,而不是把where parent设置为null呢@ballangddang@Abelisto-因为OP希望获得完整路径。从例如id=3开始,他将得到部分路径。
with recursive cte(id, parent, name, ids) as (
select id, parent, name, array[id]
from my_table
where parent is null
union all
select t.id, t.parent, concat(c.name, t.name, '/'), ids || t.id
from cte c
join my_table t on c.id = t.parent
)
select id, name
from cte
where 2 = any(ids) and id <> 2
id | name
----+-----------------------
3 | /home/user/
4 | /home/user/bin/
(2 rows)
with recursive outer_query(id, parent, name) as (
with recursive inner_query(qid, id, parent, name) as (
select id, id, parent, name
from my_table
where id = 2 -- parameter
union all
select qid, t.id, t.parent, concat(t.name, '/', q.name)
from inner_query q
join my_table t on q.parent = t.id
)
select qid, null::int, right(name, -1)
from inner_query
where parent is null
union all
select t.id, t.parent, concat(q.name, '/', t.name)
from outer_query q
join my_table t on q.id = t.parent
)
select id, name
from outer_query
where id <> 2; -- parameter