Seit Postgres die Möglichkeit hat, LATERAL
Verknüpfungen durchzuführen, habe ich mich darüber informiert, da ich derzeit komplexe Daten-Dumps für mein Team mit vielen ineffizienten Unterabfragen durchführe, bei denen die Gesamtabfrage vier Minuten oder länger dauert.
Ich verstehe, dass LATERAL
Joins mir vielleicht helfen können, aber selbst nachdem ich Artikel wie diesen von Heap Analytics gelesen habe , folge ich immer noch nicht ganz.
Was ist der Anwendungsfall für einen LATERAL
Join? Was ist der Unterschied zwischen einem LATERAL
Join und einer Unterabfrage?
sql
postgresql
subquery
lateral-join
jdotjdot
quelle
quelle
apply
ist die gleiche wie dielateral
von dem SQL - Standard)Antworten:
Eher wie eine korrelierte Unterabfrage
Ein
LATERAL
Join (Postgres 9.3 oder höher) ähnelt eher einer korrelierten Unterabfrage , nicht einer einfachen Unterabfrage. Wie Andomar betonte, muss eine Funktion oder Unterabfrage rechts von einemLATERAL
Join - genau wie eine korrelierte Unterabfrage - für jede Zeile links davon einmal ausgewertet werden, während eine einfache Unterabfrage (Tabellenausdruck) nur einmal ausgewertet wird . (Der Abfrageplaner bietet jedoch Möglichkeiten, die Leistung für beide zu optimieren.)Diese verwandte Antwort enthält Codebeispiele für beide nebeneinander, mit denen das gleiche Problem gelöst wird:
Wenn Sie mehr als eine Spalte zurückgeben , ist ein
LATERAL
Join normalerweise einfacher, sauberer und schneller.Denken Sie auch daran, dass das Äquivalent einer korrelierten Unterabfrage lautet
LEFT JOIN LATERAL ... ON true
:Lesen Sie das Handbuch weiter
LATERAL
Es ist maßgeblicher als alles, was wir hier beantworten werden:
Dinge, die eine Unterabfrage nicht kann
Es gibt Dinge, die ein
LATERAL
Join tun kann, aber eine (korrelierte) Unterabfrage kann nicht (leicht). 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 Set-Return-Funktionen sind nur in derFROM
Klausel zulässig . Wieunnest()
bei mehreren Parametern in Postgres 9.4 oder höher. Das Handbuch:Das funktioniert also, kann aber nicht einfach durch eine Unterabfrage ersetzt werden:
Das Komma (
,
) in derFROM
Klausel ist eine Kurzschreibweise fürCROSS JOIN
.LATERAL
wird für Tabellenfunktionen automatisch angenommen.Mehr zum Sonderfall von
UNNEST( array_expression [, ... ] )
:Set-Return-Funktionen in der
SELECT
ListeSie können auch Set-Return-Funktionen wie
unnest()
in derSELECT
Liste direkt verwenden. Dies zeigte ein überraschendes Verhalten mit mehr als einer solchen Funktion in derselbenSELECT
Liste bis zu Postgres 9.6. Aber es wurde endlich mit Postgres 10 bereinigt und ist jetzt eine gültige Alternative (auch wenn es sich nicht um Standard-SQL handelt). Sehen:Aufbauend auf dem obigen Beispiel:
Vergleich:
dbfiddle für pg 9.6 hier
dbfiddle für pg 10 hier
Klären Sie Fehlinformationen
Das Handbuch:
Diese beiden Abfragen sind also gültig (auch wenn sie nicht besonders nützlich sind):
Während dieser nicht ist:
Aus diesem Grund ist das Codebeispiel von @ Andomar korrekt (für das
CROSS JOIN
keine Join-Bedingung erforderlich ist) und das von @ Attilaistungültig.quelle
LATERAL
Unterabfrage zu demonstrieren : gis.stackexchange.com/a/230070/7244Der Unterschied zwischen einem Nicht-
lateral
und einemlateral
Join besteht darin, ob Sie in die Zeile der linken Tabelle schauen können. Beispielsweise:Dieses "nach außen gerichtete" bedeutet, dass die Unterabfrage mehr als einmal ausgewertet werden muss. Immerhin
t1.col1
können viele Werte annehmen.Im Gegensatz dazu kann die Unterabfrage nach einem Nicht-
lateral
Join einmal ausgewertet werden:Wie ohne erforderlich
lateral
, hängt die innere Abfrage in keiner Weise von der äußeren Abfrage ab. Einelateral
Abfrage istcorrelated
aufgrund ihrer Beziehung zu Zeilen außerhalb der Abfrage selbst ein Beispiel für eine Abfrage.quelle
select * from table1 left join t2 using (col1)
vergleicht man? Es ist mir unklar, wann ein Join mit / on-Bedingung nicht ausreicht und es sinnvoller wäre, lateral zu verwenden.Erstens ist Lateral und Cross Apply dasselbe . Daher können Sie auch über Cross Apply lesen. Da es seit Ewigkeiten in SQL Server implementiert ist, finden Sie weitere Informationen dazu als Lateral.
Zweitens gibt es nach meinem Verständnis nichts, was Sie nicht mit Unterabfragen anstelle von Lateral tun können. Aber:
Betrachten Sie die folgende Abfrage.
In diesem Zustand können Sie lateral verwenden.
In dieser Abfrage können Sie aufgrund der Limit-Klausel keinen normalen Join verwenden. Lateral oder Cross Apply kann verwendet werden, wenn keine einfache Join-Bedingung vorliegt .
Es gibt mehr Verwendungen für seitliche oder Kreuzanwendung, aber dies ist die häufigste, die ich gefunden habe.
quelle
lateral
stattapply
. Vielleicht hat Microsoft die Syntax patentiert?lateral
ist im SQL-Standard,apply
ist es aber nicht.LEFT JOIN
erfordert eine Join-Bedingung. Machen SieON TRUE
es, es sei denn, Sie möchten irgendwie einschränken.cross join
oder eineon
BedingungNiemand hat darauf hingewiesen, dass Sie
LATERAL
Abfragen verwenden können, um eine benutzerdefinierte Funktion auf jede ausgewählte Zeile anzuwenden.Zum Beispiel:
Nur so kann ich so etwas in PostgreSQL machen.
quelle