PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Zapytanie PostgreSQL SQL do przemierzania całego nieskierowanego grafu i zwracania wszystkich znalezionych krawędzi

Doszedłem do tego, nie powinno wchodzić w nieskończone pętle z jakimikolwiek danymi:

--create temp table edges ("from" text, "to" text);
--insert into edges values ('initial_node', 'a'), ('a', 'b'), ('a', 'c'), ('c', 'd');

with recursive graph(points) as (
  select array(select distinct "to" from edges where "from" = 'initial_node')
  union all
  select g.points || e1.p || e2.p
  from graph g
  left join lateral (
    select array(
      select distinct "to"
      from edges 
      where "from" =any(g.points) and "to" <>all(g.points) and "to" <> 'initial_node') AS p) e1 on (true)
  left join lateral (
    select array(
      select distinct "from"
      from edges 
      where "to" =any(g.points) and "from" <>all(g.points) and "from" <> 'initial_node') AS p) e2 on (true)
  where e1.p <> '{}' OR e2.p <> '{}'
  )
select distinct unnest(points)
from graph
order by 1

Zapytania rekurencyjne są bardzo ograniczone pod względem tego, co można wybrać, a ponieważ nie pozwalają na użycie wyników rekurencyjnych wewnątrz podselekcji, nie można użyć NOT IN (wybierz * z rekurencyjnego gdzie...). Przechowywanie wyników w tablicy, użycie LEFT JOIN LATERAL oraz użycie =ANY() i <>ALL() rozwiązało tę zagadkę.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Alternatywa w przypadku wprowadzenia klauzuli IN DUŻO wartości (postgreSQL)

  2. Wartości tablic są wyświetlane wiersz po wierszu dla pojedynczego identyfikatora za pomocą Postgresql

  3. Testuj funkcję zerową przy różnych parametrach

  4. Ewolucja tolerancji błędów w PostgreSQL:Synchronous Commit

  5. foreach %dopar% + RPostgreSQL