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

El registro devuelto por la función tiene columnas concatenadas

Generalmente, para descomponer filas devuelto de una función y obtiene columnas individuales:

SELECT * FROM account_servicetier_for_day(20424, '2014-08-12');

En cuanto a la consulta:

Postgres 9.3 o posterior

Limpiador con JOIN LATERAL :

SELECT '2014-08-12' AS day, 0 AS inbytes, 0 AS outbytes
     , a.username, a.accountid, a.userid
     , f.*   -- but avoid duplicate column names!
FROM   account_tab a
     , account_servicetier_for_day(a.accountid, '2014-08-12') f  -- <-- HERE
WHERE  a.isdsl = 1
AND    a.dslservicetypeid IS NOT NULL
AND    NOT EXISTS (
   SELECT 1
   FROM   dailyaccounting_tab
   WHERE  day = '2014-08-12'
   AND    accountid = a.accountid
   )
ORDER  BY a.username;

El LATERAL La palabra clave está implícita aquí, las funciones siempre pueden referirse a FROM anteriores. artículos. El manual:

LATERAL también puede preceder a una llamada de función FROM elemento, pero en este caso es una palabra irrelevante, porque la expresión de la función puede referirse a un FROM anterior artículos en cualquier caso.

Relacionado:

  • Insertar varias filas en una tabla según el número en otra tabla

Notación abreviada con una coma en FROM list es (en su mayoría) equivalente a CROSS JOIN LATERAL (igual que [INNER] JOIN LATERAL ... ON TRUE ) y, por lo tanto, elimina filas del resultado donde la llamada a la función no devuelve ninguna fila. Para conservar dichas filas, utilice LEFT JOIN LATERAL ... ON TRUE :

...
FROM  account_tab a
LEFT  JOIN LATERAL account_servicetier_for_day(a.accountid, '2014-08-12') f ON TRUE
...

Además, no use NOT IN (subquery) cuando puedes evitarlo. Es la forma más lenta y complicada de hacerlo:

  • Seleccionar filas que no están presentes en otra tabla

Sugiero NOT EXISTS en su lugar.

Postgres 9.2 o anterior

Puede llamar a una función de devolución de conjuntos en SELECT list (que es una extensión de Postgres de SQL estándar). Por motivos de rendimiento, es mejor hacerlo en una subconsulta. Descomponga el tipo de fila (¡bien conocido!) en la consulta externa para evitar la evaluación repetida de la función:

SELECT '2014-08-12' AS day, 0 AS inbytes, 0 AS outbytes
     , a.username, a.accountid, a.userid
     , (a.rec).*   -- but avoid duplicate column names!
FROM  (
   SELECT *, account_servicetier_for_day(a.accountid, '2014-08-12') AS rec
   FROM   account_tab a
   WHERE  a.isdsl = 1
   AND    a.dslservicetypeid Is Not Null
   AND    NOT EXISTS (
       SELECT 1
       FROM   dailyaccounting_tab
       WHERE  day = '2014-08-12'
       AND    accountid = a.accountid
      )
   ) a
ORDER  BY a.username;

Respuesta relacionada de Craig Ringer con una explicación, por qué es mejor descomponer en la consulta externa:

  • ¿Cómo evitar múltiples evaluaciones de funciones con la sintaxis (func()).* en una consulta SQL?

Postgres 10 eliminó las rarezas en el comportamiento de las funciones de devolución de conjuntos en SELECT :

  • ¿Cuál es el comportamiento esperado para varias funciones de devolución de conjuntos en la cláusula SELECT?