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

Rekursiv forespørgsel brugt til transitiv lukning

Du kan forenkle flere steder (forudsat acct_id og parent_id er IKKE 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;
  • Kolonnerne acct_id , dybde , cyklus er bare støj i din forespørgsel.
  • HVOR betingelse skal forlade rekursionen et trin tidligere, før duplikatindtastningen fra den øverste node er i resultatet. Det var en "off-by-one" i din original.

Resten formateres.

Hvis du ved det den eneste mulige cirkel i din graf er en selvreference, det kan vi få billigere:

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 Fiddle.

Bemærk, at der ville være problemer (i det mindste op til side v9.4) for datatyper med en modifikator (såsom varchar(5) ) fordi array-sammenkædning mister modifikationen, men rCTE insisterer på, at typer matcher nøjagtigt:

  • Overraskende resultater for datatyper med typemodifikator


  1. Sådan bruges SQL Server AlwaysOn-funktioner

  2. Fix Msg 8116 "Argumentdatatypedatoen er ugyldig for argument 1 for substring-funktionen" i SQL Server

  3. Postgres:konverter enkelt række til flere rækker (unpivot)

  4. Ugyldigt parameternummer:parameter blev ikke defineret Indsætter data