Czy kolejność łączenia ma znaczenie w SQL?

189

Niezależnie od wydajności, czy otrzymam ten sam wynik z poniższych zapytań A i B? A co z C i D?

-- A
select *
from   a left join b
           on <blahblah>
       left join c
           on <blahblan>


-- B
select *
from   a left join c
           on <blahblah>
       left join b
           on <blahblan>  

-- C
select *
from   a join b
           on <blahblah>
       join c
           on <blahblan>


-- D
select *
from   a join c
           on <blahblah>
       join b
           on <blahblan>  
Tylko uczeń
źródło
11
Co jest <blahblah>? czy dołączasz do A do B i od A do C, czy dołączasz do A do B i B do C?
beny23
2
Cześć Beny, kod w moim pytaniu jest abstrakcją. Nie martwię się o dołączenie A do B lub A do C, chcę tylko wiedzieć, czy taka składnia zapewni identyczne wyniki.
Tylko uczeń

Odpowiedzi:

225

W przypadku INNERdołączeń nie, kolejność nie ma znaczenia. Zapytania zwrócą te same wyniki, o ile zmienisz wybrane opcje z SELECT *na SELECT a.*, b.*, c.*.


Dla ( LEFT, RIGHTlub FULL) OUTERsprzężeń, tak, sprawy zamówienie - i ( zaktualizowane ) rzeczy są o wiele bardziej skomplikowane.

Po pierwsze, połączenia zewnętrzne nie są przemienne, więc a LEFT JOIN bnie są takie same jakb LEFT JOIN a

Sprzężenia zewnętrzne również nie są asocjacyjne, więc w twoich przykładach, które dotyczą obu właściwości (przemienności i asocjatywności):

a LEFT JOIN b 
    ON b.ab_id = a.ab_id
  LEFT JOIN c
    ON c.ac_id = a.ac_id

odpowiada :

a LEFT JOIN c 
    ON c.ac_id = a.ac_id
  LEFT JOIN b
    ON b.ab_id = a.ab_id

ale:

a LEFT JOIN b 
    ON  b.ab_id = a.ab_id
  LEFT JOIN c
    ON  c.ac_id = a.ac_id
    AND c.bc_id = b.bc_id

nie jest równoważne z :

a LEFT JOIN c 
    ON  c.ac_id = a.ac_id
  LEFT JOIN b
    ON  b.ab_id = a.ab_id
    AND b.bc_id = c.bc_id

Kolejny (miejmy nadzieję prostszy) przykład asocjatywności. Pomyśl o tym jako (a LEFT JOIN b) LEFT JOIN c:

a LEFT JOIN b 
    ON b.ab_id = a.ab_id          -- AB condition
 LEFT JOIN c
    ON c.bc_id = b.bc_id          -- BC condition

Jest to równoważne z a LEFT JOIN (b LEFT JOIN c):

a LEFT JOIN  
    b LEFT JOIN c
        ON c.bc_id = b.bc_id          -- BC condition
    ON b.ab_id = a.ab_id          -- AB condition

tylko dlatego, że mamy „miłe” ONwarunki. Zarówno ON b.ab_id = a.ab_idi c.bc_id = b.bc_idsą kontrole równości i nie wiążą się NULLporównań.

Można nawet mieć warunki z innymi operatorami lub bardziej skomplikowanych, takich jak: ON a.x <= b.xlub ON a.x = 7lub ON a.x LIKE b.xlub ON (a.x, a.y) = (b.x, b.y)i dwa zapytania nadal byłyby równoważne.

Jeśli jednak którykolwiek z nich dotyczy IS NULLlub funkcja jest powiązana z zerami COALESCE(), na przykład jeśli warunek był spełniony b.ab_id IS NULL, wówczas dwa zapytania nie byłyby równoważne.

ypercubeᵀᴹ
źródło
3
Bardziej słuszne jest stwierdzenie, że łączenie zewnętrzne jest asocjacyjne, o ile żaden predykat nie może być spełniony przez wiersz, w którym wszystkie kolumny z jednej tabeli mają wartość NULL, niż stwierdzenie, że jest ono asocjacyjne, o ile predykaty nie dotyczą IS NULL lub „funkcja powiązana z zerami”. Można łatwo wyobrazić sobie predykat, który spełnia pierwszy opis, ale nie drugi, jak a.somecol > 0 OR b.someothercol > 0; skojarzenie może się nie powieść dla tego stanu.
Mark Amery
Ale tak, myślę, że technicznie prawdą jest twierdzenie, że OUTER JOIN jest asocjacyjny, o ile predykat nie spełnia żadnego z opisanych tutaj warunków: stackoverflow.com/questions/20022196/... (pierwszy z nich również psuje skojarzenie w przypadku WEJŚĆ WEWNĘTRZNYCH, ale jest to tak tanie i oczywiste podejście do przełamania go, że być może nie warto o nim wspominać.) Warto również zauważyć, że najpopularniejszy rodzaj POŁĄCZENIA - DOŁĄCZENIE do klucza obcego - nie spełnia żadnego z tych warunków i dlatego jest miły i asocjacyjny.
Mark Amery
1
@MarkAmery Dziękuję, miałem trudności z ułożeniem zdań w tym punkcie (i już głosowałem tę odpowiedź;)
ypercubeᵀᴹ
ypercube mam INNER JOINi następujące LEFT JOIN. Czy to działa tak, że najpierw kwerenda będzie na Filterpodstawie rekordów, INNER JOINa następnie zastosuje się LEFT JOINdo nich Filtered?
Muhammad Babar
W rzeczywistości wszystkie typy łączenia asocjacyjne, jak określono w standardzie SQL i zgodnie z matematycznymi definicjami asocjatywności, ale nie wydają się one asocjatywne, ponieważ przestawienie nawiasów wymaga przeniesienia ONklauzuli (tj. „Specyfikacji łączenia”) do nowej lokalizacji . Jest to jednak tylko składnia. Jeśli użyjesz notacji algebry relacyjnej (gdzie specyfikacja łączenia jest umieszczona poniżej operatora łączenia), wówczas skojarzenie staje się bardziej widoczne. Twój argument pokazuje tylko, że sprzężenia zewnętrzne nie są przemienne , co jest poprawne
Lukas Eder
4

dla zwykłych dołączeń tak nie jest. TableA join TableBstworzy taki sam plan wykonania jak TableB join TableA(więc twoje przykłady C i D byłyby takie same)

dla lewych i prawych połączeń to robi. TableA left Join TableBjest inny niż TableB left Join TableA, ale jest taki sam jakTableB right Join TableA

Diego
źródło
4
Dotyczy to tylko komutatywności, ale przykłady w pytaniu pokazują, że pytający jest zainteresowany skojarzeniem. Odpowiedź ypercube dotyczy obu tych kwestii.
Mark Amery
2

Jeśli spróbujesz dołączyć do C na polu z B przed dołączeniem do B, tj .:

SELECT A.x, A.y, A.z FROM A 
   INNER JOIN C
       on B.x = C.x
   INNER JOIN b
       on A.x = B.x

Twoje zapytanie nie powiedzie się, więc w tym przypadku kolejność ma znaczenie.

Teo J.
źródło
Tak, to prawda, poprawna odpowiedź powinna zostać zmieniona.
Nir Pengas,
-2

Optymalizator Oracle wybiera kolejność łączenia tabel dla łączenia wewnętrznego. Optymalizator wybiera kolejność łączenia tabel tylko w prostych klauzulach FROM. U może sprawdzić dokumentację wyroczni na swojej stronie internetowej. A dla lewych, prawych stron zewnętrznych najbardziej głosowana odpowiedź jest odpowiednia. Optymalizator wybiera optymalną kolejność łączenia, a także optymalny indeks dla każdej tabeli. Kolejność łączenia może mieć wpływ na to, który indeks jest najlepszym wyborem. Optymalizator może wybrać indeks jako ścieżkę dostępu do tabeli, jeśli jest to tabela wewnętrzna, ale nie, jeśli jest to tabela zewnętrzna (i nie ma dalszych kwalifikacji).

Optymalizator wybiera kolejność łączenia tabel tylko w prostych klauzulach FROM. Większość złączeń za pomocą słowa kluczowego JOIN jest spłaszczonych do prostych złączeń, więc optymalizator wybiera kolejność łączenia.

Optymalizator nie wybiera kolejności łączenia dla połączeń zewnętrznych; używa kolejności określonej w instrukcji.

Przy wyborze kolejności łączenia optymalizator bierze pod uwagę: Rozmiar każdej tabeli Indeksy dostępne w każdej tabeli Czy indeks w tabeli jest przydatny w określonej kolejności łączenia Liczba wierszy i stron do skanowania dla każdej tabeli w każdej dołączyć do zamówienia

Saumyojit Das
źródło