PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Rekursive Abfrage, die für den transitiven Abschluss verwendet wird

Sie können an mehreren Stellen vereinfachen (vorausgesetzt acct_id und parent_id sind NOT NULL ):

WITH RECURSIVE search_graph AS (
   SELECT parent_id, ARRAY[acct_id] AS path
   FROM   account

   UNION  ALL
   SELECT g.parent_id, sg.path || g.acct_id
   FROM   search_graph sg
   JOIN   account g ON g.acct_id = sg.parent_id 
   WHERE  g.acct_id <> ALL(sg.path)
   )
SELECT path[1] AS child
     , path[array_upper(path,1)] AS parent
     , path
FROM   search_graph
ORDER  BY path;
  • Die Spalten acct_id , depth , cycle sind nur Rauschen in deiner Abfrage.
  • Das WHERE Bedingung muss die Rekursion einen Schritt früher verlassen, vor der doppelte Eintrag vom obersten Knoten ist im Ergebnis. Das war in deinem Original ein "off-by-one".

Der Rest ist Formatierung.

Wenn Sie wissen der einzig mögliche Kreis in Ihrem Diagramm ist eine Selbstreferenz, das können wir billiger haben:

WITH RECURSIVE search_graph AS (
   SELECT parent_id, ARRAY[acct_id] AS path, acct_id <> parent_id AS keep_going
   FROM   account

   UNION  ALL
   SELECT g.parent_id, sg.path || g.acct_id, g.acct_id <> g.parent_id
   FROM   search_graph sg
   JOIN   account g ON g.acct_id = sg.parent_id 
   WHERE  sg.keep_going
)
SELECT path[1] AS child
     , path[array_upper(path,1)] AS parent
     , path
FROM   search_graph
ORDER  BY path;

SQL-Geige.

Beachten Sie, dass es Probleme geben würde (zumindest bis pg v9.4) für Datentypen mit einem Modifikator (wie varchar(5) ), weil die Array-Verkettung den Modifikator verliert, aber der rCTE darauf besteht, dass die Typen genau übereinstimmen:

  • Überraschende Ergebnisse für Datentypen mit Typmodifikator