Was ist a LATERAL
beitreten?
Die Funktion wurde mit PostgreSQL 9.3 eingeführt. Das Handbuch:
Unterabfragen, die in FROM
erscheinen kann das Schlüsselwort LATERAL
vorangestellt werden . Dadurch können sie auf Spalten verweisen, die durch vorangestelltes FROM
bereitgestellt werden Produkte. (Ohne LATERAL
, wird jede Unterabfrage unabhängig ausgewertet und kann daher nicht auf andere FROM
verweisen Element.)
Tabellenfunktionen, die in FROM
erscheinen kann auch das Schlüsselwort LATERAL
vorangestellt werden , aber für Funktionen ist das Schlüsselwort optional; Die Argumente der Funktion können Verweise auf Spalten enthalten, die durch vorangestelltes FROM
bereitgestellt werden Artikel auf jeden Fall.
Dort finden Sie grundlegende Codebeispiele.
Eher wie eine korrelierte Unterabfrage
A LATERAL
join ist eher wie eine korrelierte Unterabfrage, nicht eine einfache Unterabfrage, da die Ausdrücke rechts von einem LATERAL
stehen Join werden einmal für jede Zeile links davon ausgewertet - genau wie ein correlated Unterabfrage - während eine einfache Unterabfrage (Tabellenausdruck) einmal ausgewertet wird nur. (Der Abfrageplaner hat jedoch Möglichkeiten, die Leistung für beide zu optimieren.)
Verwandte Antwort mit Codebeispielen für beide nebeneinander, die dasselbe Problem lösen:
- Optimieren Sie die GROUP BY-Abfrage, um die neueste Zeile pro Benutzer abzurufen
Zur Rückgabe von mehr als einer Spalte , ein LATERAL
Join ist normalerweise einfacher, sauberer und schneller.
Denken Sie auch daran, dass das Äquivalent einer korrelierten Unterabfrage LEFT JOIN LATERAL ... ON true
ist :
- Rufen Sie eine Set-zurückgebende Funktion mehrmals mit einem Array-Argument auf
Dinge, die eine Unterabfrage nicht kann
Es gibt Dinge, die ein LATERAL
join kann dies tun, aber eine (korrelierte) Unterabfrage kann dies (ohne weiteres) nicht. Eine korrelierte Unterabfrage kann nur einen einzelnen Wert zurückgeben, nicht mehrere Spalten und nicht mehrere Zeilen – mit Ausnahme von bloßen Funktionsaufrufen (die Ergebniszeilen multiplizieren, wenn sie mehrere Zeilen zurückgeben). Aber auch bestimmte satzrückgebende Funktionen sind nur im FROM
erlaubt Klausel. Wie unnest()
mit mehreren Parametern in Postgres 9.4 oder höher. Das Handbuch:
Dies ist nur im FROM
erlaubt Klausel;
Das funktioniert also, kann aber nicht (leicht) durch eine Unterabfrage ersetzt werden:
CREATE TABLE tbl (a1 int[], a2 int[]);
SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2); -- implicit LATERAL
Das Komma (,
) im FROM
-Klausel ist eine Kurzschreibweise für CROSS JOIN
.LATERAL
wird automatisch für Tabellenfunktionen angenommen.
Über den Spezialfall von UNNEST( array_expression [, ... ] )
:
- Wie deklarieren Sie eine Set-Returning-Funktion so, dass sie nur in der FROM-Klausel erlaubt ist?
Set-zurückgebende Funktionen im SELECT
Liste
Sie können auch Set-Returning-Funktionen wie unnest()
verwenden im SELECT
direkt auflisten. Dies zeigte früher ein überraschendes Verhalten mit mehr als einer solchen Funktion im selben SELECT
Liste bis Postgres 9.6. Aber es wurde endlich mit Postgres 10 bereinigt und ist jetzt eine gültige Alternative (auch wenn es kein Standard-SQL ist). Siehe:
- Was ist das erwartete Verhalten für mehrere Set-zurückgebende Funktionen in der SELECT-Klausel?
Aufbauend auf obigem Beispiel:
SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM tbl;
Vergleich:
dbfiddle für pg 9.6 hier
dbfiddle für Seite 10 hier
Klarstellen von Fehlinformationen
Das Handbuch:
Für INNER
und OUTER
Join-Typen muss eine Join-Bedingung angegeben werden, nämlich genau eine von NATURAL
, ON
join_condition , oder USING
(join_column [, ...]). Siehe unten für die Bedeutung.
Für CROSS JOIN
, darf keiner dieser Klauseln vorkommen.
Diese beiden Abfragen sind also gültig (auch wenn sie nicht besonders nützlich sind):
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t ON TRUE;
SELECT *
FROM tbl t, LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
Während dies nicht der Fall ist:
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
Deshalb ist das Codebeispiel von Andomar korrekt (der CROSS JOIN
erfordert keine Join-Bedingung) und Attilas ist war nicht.