रिकर्सिव कॉमन टेबल एक्सप्रेशन
का इस्तेमाल करें . हमेशा रूट से शुरू करते हुए, किसी दिए गए id
. के लिए पथ प्राप्त करने के लिए id की एक सरणी का उपयोग करें WHERE
. में खंड।
id = 1
. के लिए :
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 1 = any(ids) and id <> 1
id | name
----+-----------------------
2 | /home/
5 | /usr/
6 | /usr/local/
3 | /home/user/
4 | /home/user/bin/
(5 rows)
id = 2
. के लिए :
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