Im Allgemeinen um Zeilen zu zerlegen von einer Funktion zurückgegeben und einzelne Spalten erhalten:
SELECT * FROM account_servicetier_for_day(20424, '2014-08-12');
Was die Abfrage angeht:
Postgres 9.3 oder neuer
Reiniger mit 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;
Der LATERAL
Schlüsselwort ist hier implizit, Funktionen können sich immer auf früheres FROM
beziehen Produkte. Das Handbuch:
LATERAL
kann auch vor einem Funktionsaufruf FROM
stehen item, aber in diesem Fall handelt es sich um ein Füllwort, da der Funktionsausdruck auf frühere FROM
verweisen kann Artikel auf jeden Fall.
Verwandte:
- Einfügen mehrerer Zeilen in eine Tabelle basierend auf Zahlen in einer anderen Tabelle
Kurzschreibweise mit Komma im FROM
list ist (meistens) äquivalent zu einem CROSS JOIN LATERAL
(dasselbe wie [INNER] JOIN LATERAL ... ON TRUE
) und entfernt somit Zeilen aus dem Ergebnis, wo der Funktionsaufruf keine Zeile zurückgibt. Um solche Zeilen beizubehalten, verwenden Sie LEFT JOIN LATERAL ... ON TRUE
:
...
FROM account_tab a
LEFT JOIN LATERAL account_servicetier_for_day(a.accountid, '2014-08-12') f ON TRUE
...
Verwenden Sie außerdem nicht NOT IN (subquery)
wenn Sie es vermeiden können. Dies ist die langsamste und kniffligste von mehreren Möglichkeiten, dies zu tun:
- Wählen Sie Zeilen aus, die in keiner anderen Tabelle vorhanden sind
Ich empfehle NOT EXISTS
stattdessen.
Postgres 9.2 oder älter
Sie können im SELECT
eine set-returning-Funktion aufrufen list (eine Postgres-Erweiterung von Standard-SQL). Dies geschieht aus Performance-Gründen am besten in einer Unterabfrage. Zerlegen Sie den (bekannten!) Zeilentyp in der äußeren Abfrage, um eine wiederholte Auswertung der Funktion zu vermeiden:
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;
Verwandte Antwort von Craig Ringer mit einer Erklärung, warum wir besser in der äußeren Abfrage zerlegen:
- Wie kann man mehrere Funktionsauswertungen mit der (func()).*-Syntax in einer SQL-Abfrage vermeiden?
Postgres 10 Kuriositäten im Verhalten von Set-zurückgebenden Funktionen in SELECT
entfernt :
- Was ist das erwartete Verhalten für mehrere Set-zurückgebende Funktionen in der SELECT-Klausel?