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?