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?