update2这是一个函数,它执行得很好,因为搜索只在路径内进行,从父级开始:
create or replace function get_item(path text[])
returns items
as
$$
with recursive cte as (
select i.id, i.name, i.parent_id, 1 as level
from items as i
where i.parent_id is null and i.name = $1[1]
union all
select i.id, i.name, i.parent_id, c.level + 1
from items as i
inner join cte as c on c.id = i.parent_id
where i.name = $1[level + 1]
)
select c.id, c.parent_id, c.name
from cte as c
where c.level = array_length($1, 1)
$$
language sql;
sql fiddle demo
更新我认为你可以进行递归遍历。我写过这个的sql版本,所以因为cte有点乱,但是可以写一个函数:
with recursive cte_path as (
select array['holiday', 'spain', '2013'] as arr
), cte as (
select i.id, i.name, i.parent_id, 1 as level
from items as i
cross join cte_path as p
where i.parent_id is null and name = p.arr[1]
union all
select i.id, i.name, i.parent_id, c.level + 1
from items as i
inner join cte as c on c.id = i.parent_id
cross join cte_path as p
where i.name = p.arr[level + 1]
)
select c.*
from cte as c
cross join cte_path as p
where level = array_length(p.arr, 1)
sql fiddle demo
或者您可以使用递归 cte 为所有元素构建路径并将路径累积到数组或字符串中:
with recursive cte as (
select i.id, i.name, i.parent_id, i.name::text as path
from items as i
where i.parent_id is null
union all
select i.id, i.name, i.parent_id, c.path || '->' || i.name::text as path
from items as i
inner join cte as c on c.id = i.parent_id
)
select *
from cte
where path = 'holiday->spain->2013';
或者
with recursive cte as (
select i.id, i.name, i.parent_id, array[i.name::text] as path
from items as i
where i.parent_id is null
union all
select i.id, i.name, i.parent_id, c.path || array[i.name::text] as path
from items as i
inner join cte as c on c.id = i.parent_id
)
select *
from cte
where path = array['holiday', 'spain', '2013']
sql fiddle demo