2009-07-07 13 views
6

Prawdopodobnie powinienem już to wiedzieć, ale co, jeśli jest jakaś różnica między tymi dwoma stwierdzeniami?SQL - Różnica między tymi Joins?

zagnieżdżona dołączyć:

SELECT 
    t1.* 
FROM 
    table1 t1 
    INNER JOIN table2 t2 
     LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 
    ON t2.table2_ID = t1.table1_ID 

bardziej tradycyjnych społeczności:

SELECT 
    t1.* 
FROM 
    table1 t1 
    INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID 
    LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 
+0

Czy dają taki sam wynik, gdy je wykonujesz? –

+0

+1 za to, że mnie "Hm ..." – Tomalak

+0

To jest o wiele łatwiejsze do zrozumienia drugiego niż pierwszego - nawet jeśli umieścisz (parens) wokół LOJ w pierwszym. Czekam na głosowanie dobrą odpowiedzią na ten temat. –

Odpowiedz

5

Cóż, to kolejność operacji ..

SELECT 
    t1.* 
FROM 
    table1 t1 
    INNER JOIN table2 t2 
     LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 
    ON t2.table2_ID = t1.table1_ID 

może być zapisane jako:

SELECT 
    t1.* 
FROM 
     table1 t1              -- inner join t1 
    INNER JOIN 
     (table2 t2 LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID) -- with this 
    ON t2.table2_ID = t1.table1_ID          -- on this condition 

Więc w zasadzie, najpierw LEFT JOIN T2 T3, na podstawie warunku przyłączenia: table3_ID = table2_ID, to INNER JOIN t1 z t2 na table2_ID = table1_ID.

W twoim drugim przykładzie najpierw INNER DOŁĄCZ t1 z t2, a następnie LEWY DOŁĄCZ do wynikowego połączenia wewnętrznego z tabelą t3 na warstwie table2_ID = table1_ID.

SELECT 
    t1.* 
FROM 
    table1 t1 
    INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID 
    LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID   

może być zapisane jako:

SELECT 
    t1.* 
FROM 
     (table1 t1 INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID) -- first inner join 
    LEFT JOIN               -- then left join 
     table3 t3 ON t3.table3_ID = t2.table2_ID      -- the result with this 

EDIT

przepraszam. Moja pierwsza uwaga była błędna. Te dwa zapytania dadzą takie same wyniki, ale może występować różnica w wydajności, ponieważ pierwsze zapytanie może działać wolniej niż drugie zapytanie w niektórych przypadkach (gdy tabela 1 zawiera tylko podzbiór elementów w tabeli 2), ponieważ LEWY JOIN będzie najpierw wykonać, a dopiero potem przeciąć tabelę1. W przeciwieństwie do drugiej kwerendy, która pozwala optymalizatorowi kwerendy wykonać to zadanie.

+1

Oczywiście kolejność operacji jest inna, ale czy istnieje jakaś faktyczna różnica (wydajność, wyniki, cokolwiek)? –

+1

Podaj przykład danych, w których zapytania będą zwracać różne wyniki. Nie udało mi się wygenerować żadnego. –

+0

OK, dzięki za przemyślenia na temat tych gości. To prawie tak, jak myślałem wtedy. Wyniki będą takie same, ale zapytania mogą działać inaczej. Myślę, że dla łatwości użycia zmienię stare (zagnieżdżone) zapytanie, aby użyć bardziej tradycyjnej składni. – TehOne

4

dla konkretnego przykładu, nie sądzę, nie powinno być żadnej różnicy w planach zapytania wygenerowane, ale zdecydowanie istnieje różnica w czytelności. Twój drugi przykład jest DUŻO łatwiejszy do naśladowania.

Jeśli chcesz odwrócić typy połączeń w tym przykładzie, możesz otrzymać dużo inne wyniki.

SELECT t1.* 
FROM table1 t1 
    LEFT JOIN table2 t2 ON t2.table2_ID = t1.table1_ID 
    INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 

-- may not produce the same results as... 

SELECT t1.* 
FROM table1 t1 
    LEFT JOIN table2 t2 
     INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 
    ON t2.table2_ID = t1.table1_ID 

Opierając się na fakcie, że kolejność sprzężeń ma znaczenia, w wielu przypadkach - ostrożny myśl powinna iść w jaki piszesz swoje dołączyć składni. Jeśli okaże się, że 2nd przykładem jest to, czego naprawdę chce osiągnąć, Pomyślę przepisanie zapytania, aby można było położyć większy nacisk na kolejność łączy ...

SELECT t1.* 
FROM table2 t2 
     INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID 
     RIGHT JOIN table1 t1 ON t2.table2_ID = t1.table1_ID 
2

Najlepszym sposobem sprawdzenia, co różni się w tych dwóch kwerendach, jest porównanie planu kwerend dla obu tych zapytań.

Nie ma różnicy w zestawach wyników dla tych IF są zawsze wiersze w tabela3 dla danego wiersza w tabela2.

Próbowałem go w mojej bazie danych, a różnica w planach zapytań była taka, że ​​ 1. W pierwszym zapytaniu optymalizator wybrał dokonanie sprzężenia na tabelach 2 i 3 w pierwszej kolejności. 2.W drugim zapytaniu optymalizator wybrał najpierw połączenie table1 i table2.

+0

Dla mnie plany wykonania moich prawdziwych zapytań były dokładnie takie same. – TehOne

0

Nie powinno być żadnej różnicy pomiędzy tymi dwoma zapytaniami, pod warunkiem, że optymalizator DBMS jest gotowy do zera. To jednak, nawet na dużych, żelaznych platformach o wysokich kosztach, nie jest założeniem, którego byłbym pewny, więc nie byłbym zaskoczony, gdyby odkryłem, że plany zapytań (iw konsekwencji czasy wykonania) są różne.

Powiązane problemy