sql >> Database teknologi >  >> RDS >> PostgreSQL

hvordan kan jeg få alle id'er fra et givet id rekursivt i en postgresql-tabel, der refererer til sig selv?

Brug rekursivt almindeligt tabeludtryk . Start altid fra roden, brug en række id'er til at få stier til et givet id i WHERE klausul.

For 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)

For 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)    

Tovejs forespørgsel

Spørgsmålet er virkelig interessant. Ovenstående forespørgsel fungerer godt, men er ineffektiv, da den analyserer alle træknuder, selv når vi beder om et blad. Den mere kraftfulde løsning er en tovejs rekursiv forespørgsel. Den indre forespørgsel går fra en given node til toppen, mens den ydre går fra noden til bunden.

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. Hvordan ændres MySQL-tidszone i en databaseforbindelse ved hjælp af Java?

  2. Opret en SQL Server-database med SQLOPS

  3. Hvordan man formulerer en forespørgsel for at vise alle kurser taget af en person

  4. CONCAT med GROUP_CONCAT i mysql