sql >> Base de Datos >  >> RDS >> PostgreSQL

Consulta recursiva utilizada para el cierre transitivo

Puede simplificar en varios lugares (suponiendo que acct_id y parent_id son 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;
  • Las columnas acct_id , depth , cycle son solo ruido en su consulta.
  • El WHERE la condición tiene que salir de la recursividad un paso antes, antes la entrada duplicada del nodo superior está en el resultado. Eso fue un "off-by-one" en su original.

El resto es formatear.

Si sabes el único círculo posible en su gráfico es una autorreferencia, podemos tener eso más barato:

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;

Violín SQL.

Tenga en cuenta que habría problemas (al menos hasta pg v9.4) para los tipos de datos con un modificador (como varchar(5) ) porque la concatenación de matrices pierde el modificador pero el rCTE insiste en que los tipos coincidan exactamente:

  • Resultados sorprendentes para tipos de datos con modificador de tipo