PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

как мога да получа всички идентификатори, започвайки от даден идентификатор рекурсивно в таблица postgresql, която се позовава на себе си?

Използвайте рекурсивен израз на обща таблица . Винаги започвайки от корена, използвайте масив от идентификатори, за да получите пътища за даден 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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Извадете два записа от една и съща колона в таблица

  2. Компактни или преномерирани идентификатори за всички таблици и нулиране на последователности до max(id)?

  3. Експортиране на PostgreSQL база данни с phpPgAdmin

  4. PHP/PostgreSQL:проверете дали вече съществува подготвен израз

  5. Актуализации на инструментите за тестване на PostgreSQL с архив за сравнителни показатели