Odkąd Postgres wyszedł z możliwością wykonywania LATERAL
połączeń, czytałem o tym, ponieważ obecnie wykonuję złożone zrzuty danych dla mojego zespołu z wieloma nieefektywnymi podzapytaniami, które sprawiają, że ogólne zapytanie zajmuje cztery minuty lub więcej.
Rozumiem, że LATERAL
łączenia mogą mi pomóc, ale nawet po przeczytaniu artykułów takich jak ten z Heap Analytics nadal nie do końca go śledzę.
Jaki jest przypadek użycia LATERAL
sprzężenia? Jaka jest różnica między LATERAL
złączeniem a podzapytaniem?
sql
postgresql
subquery
lateral-join
jdotjdot
źródło
źródło
apply
jest taki sam jak wlateral
standardzie SQL)Odpowiedzi:
Bardziej jak skorelowane podzapytanie
LATERAL
Przyłączenia (Postgresa 9,3 lub później) jest większa jak skorelowanej podzapytaniu , a nie gładkie podzapytanie. Jak zauważył Andomar , funkcja lub podzapytanie po prawej stronieLATERAL
sprzężenia musi być ocenione raz dla każdego wiersza po lewej stronie - podobnie jak podzapytanie skorelowane - podczas gdy zwykłe podzapytanie (wyrażenie tabeli) jest oceniane tylko raz . (Planer zapytań ma jednak sposoby na optymalizację wydajności w obu przypadkach).Ta pokrewna odpowiedź zawiera przykłady kodu dla obu stron, które rozwiązują ten sam problem:
Dla powracających więcej niż jedną kolumnę , o
LATERAL
przyłączenia jest zwykle prostsze, czystsze i szybsze.Pamiętaj też, że odpowiednikiem skorelowanego podzapytania jest
LEFT JOIN LATERAL ... ON true
:Przeczytaj instrukcję dalej
LATERAL
Jest bardziej autorytatywny niż cokolwiek, co zamieścimy tutaj w odpowiedziach:
Rzeczy, których podzapytanie nie może zrobić
Tam są rzeczy, które
LATERAL
łączą może zrobić, ale (skorelowane) podzapytanie nie może (łatwo). Skorelowane podzapytanie może zwracać tylko jedną wartość, a nie wiele kolumn i wiele wierszy - z wyjątkiem samych wywołań funkcji (które mnożą wiersze wynikowe, jeśli zwracają wiele wierszy). Ale nawet niektóre funkcje zwracające zbiory są dozwolone tylko wFROM
klauzuli. Podobnie jak wunnest()
przypadku wielu parametrów w Postgres 9.4 lub nowszym. Instrukcja:Więc to działa, ale nie można go łatwo zastąpić podzapytaniem:
Przecinek (
,
) wFROM
klauzuli jest krótką notacją dlaCROSS JOIN
.LATERAL
jest przyjmowany automatycznie dla funkcji tabelarycznych.Więcej o szczególnym przypadku
UNNEST( array_expression [, ... ] )
:Funkcje zwracające zestaw na
SELECT
liścieMożesz również bezpośrednio użyć funkcji zwracających zestaw, takich jak
unnest()
naSELECT
liście. Kiedyś wykazywało zaskakujące zachowanie z więcej niż jedną taką funkcją na tej samejSELECT
liście aż do Postgres 9.6. Ale w końcu został oczyszczony za pomocą Postgres 10 i jest teraz ważną alternatywą (nawet jeśli nie jest to standardowy SQL). Widzieć:Opierając się na powyższym przykładzie:
Porównanie:
dbfiddle dla strony 9.6 tutaj
dbfiddle dla strony 10 tutaj
Wyjaśnij błędne informacje
Instrukcja:
Więc te dwa zapytania są prawidłowe (nawet jeśli nie są szczególnie przydatne):
Chociaż ten nie jest:
Dlatego przykład kodu @ Andomar jest poprawny (
CROSS JOIN
nie wymaga warunku łączenia), a kod @ Attilajestnieprawidłowy.źródło
LATERAL
podzapytaniu: gis.stackexchange.com/a/230070/7244Różnica między non
lateral
-alateral
join polega na tym, czy możesz spojrzeć na wiersz tabeli po lewej stronie. Na przykład:To „wyglądające na zewnątrz” oznacza, że podzapytanie musi być ocenione więcej niż raz. Przecież
t1.col1
może przybierać wiele wartości.W przeciwieństwie do tego podzapytanie po nierozłączeniu
lateral
można ocenić raz:Jak jest to wymagane bez
lateral
, zapytanie wewnętrzne nie zależy w żaden sposób od zapytania zewnętrznego.lateral
Zapytanie jest przykłademcorrelated
zapytania, ze względu na jej związek z wierszy na zewnątrz samej zapytania.źródło
select * from table1 left join t2 using (col1)
wypada? Nie jest dla mnie jasne, kiedy połączenie przy użyciu / włączonym warunku jest niewystarczające i bardziej sensowne byłoby użycie bocznego.Po pierwsze, zastosowanie boczne i krzyżowe to to samo . Dlatego możesz również przeczytać o Cross Apply. Ponieważ był on wdrażany w SQL Server od wieków, więcej informacji na jego temat znajdziesz w sekcji Lateral.
Po drugie, zgodnie z moim rozumieniem , nie ma niczego, czego nie można zrobić za pomocą podzapytania zamiast użycia lateralnego. Ale:
Rozważ następujące zapytanie.
Możesz użyć bocznego w tym stanie.
W tym zapytaniu nie możesz używać zwykłego łączenia ze względu na klauzulę limit. Można zastosować nakładanie poprzeczne lub krzyżowe gdy nie ma prostego warunku łączenia .
Jest więcej zastosowań do nakładania bocznego lub krzyżowego, ale jest to najczęściej spotykane.
źródło
lateral
zamiastapply
. Być może Microsoft opatentował składnię?lateral
jest w standardzie SQL, aleapply
tak nie jest.LEFT JOIN
Wymaga przyłączenia warunek. Zrób to,ON TRUE
chyba że chcesz jakoś ograniczyć.cross join
lubon
Jedną z rzeczy, na które nikt nie zwrócił uwagi, jest to, że możesz użyć
LATERAL
zapytań do zastosowania funkcji zdefiniowanej przez użytkownika w każdym wybranym wierszu.Na przykład:
Tylko w ten sposób wiem, jak to zrobić w PostgreSQL.
źródło