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

Il record restituito dalla funzione ha colonne concatenate

In genere, per scomporre le righe restituito da una funzione e ottenere singole colonne:

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

Per quanto riguarda la domanda:

Postgres 9.3 o versioni successive

Pulitore 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;

Il LATERAL la parola chiave è implicita qui, le funzioni possono sempre fare riferimento a FROM precedente Oggetti. Il manuale:

LATERAL può anche precedere una chiamata di funzione FROM item, ma in questo caso è una noise word, perché l'espressione della funzione può fare riferimento a FROM precedenti in ogni caso.

Correlati:

  • Inserisci più righe in una tabella in base al numero in un'altra tabella

Notazione breve con una virgola nel FROM list è (per lo più) equivalente a un CROSS JOIN LATERAL (come [INNER] JOIN LATERAL ... ON TRUE ) e quindi rimuove le righe dal risultato in cui la chiamata di funzione non restituisce alcuna riga. Per conservare tali righe, utilizza LEFT JOIN LATERAL ... ON TRUE :

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

Inoltre, non utilizzare NOT IN (subquery) quando puoi evitarlo È il modo più lento e complicato per farlo:

  • Seleziona le righe che non sono presenti in un'altra tabella

Suggerisco NOT EXISTS invece.

Postgres 9.2 o precedente

Puoi chiamare una funzione di restituzione di set in SELECT list (che è un'estensione Postgres di SQL standard). Per motivi di prestazioni, è meglio farlo in una sottoquery. Scomponi il tipo di riga (noto!) nella query esterna per evitare la valutazione ripetuta della funzione:

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;

Risposta correlata di Craig Ringer con una spiegazione, perché è meglio scomporre nella query esterna:

  • Come evitare più valutazioni di funzioni con la sintassi (func()).* in una query SQL?

Postgres 10 rimosse le stranezze nel comportamento delle funzioni di ritorno degli insiemi nel SELECT :

  • Qual ​​è il comportamento previsto per più funzioni di restituzione di set nella clausola SELECT?