Klauzula INNER JOIN ON vs WHERE

941

Dla uproszczenia załóżmy, że wszystkie odpowiednie pola są NOT NULL.

Możesz to zrobić:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1, table2
WHERE
    table1.foreignkey = table2.primarykey
    AND (some other conditions)

Albo:

SELECT
    table1.this, table2.that, table2.somethingelse
FROM
    table1 INNER JOIN table2
    ON table1.foreignkey = table2.primarykey
WHERE
    (some other conditions)

Czy te dwa działają w ten sam sposób MySQL?

JCCyC
źródło
1
@Marco: oto jest
Alexander Malakhov
1
możliwy duplikat lewego połączenia SQL vs. wiele tabel na linii FROM?
Ciro Santilli 4 病毒 审查 六四 事件 法轮功
18
Jeśli dobrze zrozumiałem, pierwszy wariant to niejawna składnia ANSI SQL-89, a drugi wariant to jawna składnia ANSI SQL-92. Oba zaowocują takim samym wynikiem w zgodnych implementacjach SQL i oba spowodują ten sam plan zapytań w dobrze wykonanych implementacjach SQL. Ja osobiście wolę składnię SQL-89, ale wiele osób woli składnię SQL-92.
Mikko Rantalainen
11
@Hogan Wskazałem oficjalne nazwy dla różnych składni. Żadna z odpowiedzi nie określiła wprost pełnych nazwisk, dlatego postanowiłem dodać je jako komentarze. Jednak mój komentarz nie odpowiedział na rzeczywiste pytanie, dlatego dodałem to jako komentarz, a nie jako odpowiedź. (Wysoko głosowane odpowiedzi twierdzą, że „INNER JOIN jest składnią ANSI” i „domyślna składnia ANSI jest starsza”, która nic nie mówi, ponieważ obie składnie są różnymi składniami ANSI.)
Mikko Rantalainen

Odpowiedzi:

710

INNER JOIN to składnia ANSI, której powinieneś użyć.

Jest to ogólnie uważane za bardziej czytelne, szczególnie gdy dołączasz do wielu tabel.

Można go również łatwo zastąpić, OUTER JOINgdy zajdzie taka potrzeba.

WHERESkładnia jest bardziej zorientowany model relacyjny.

Wynikiem dwóch tabel JOINed jest iloczyn kartezjański tabel, do których stosowany jest filtr, który wybiera tylko te wiersze z pasującymi łączącymi kolumnami.

Łatwiej to zauważyć dzięki WHEREskładni.

Na przykład w MySQL (i ogólnie w SQL) te dwa zapytania są synonimami.

Zauważ również, że MySQL ma również STRAIGHT_JOINklauzulę.

Za pomocą tej klauzuli można kontrolować JOINkolejność: która tabela jest skanowana w pętli zewnętrznej, a która w pętli wewnętrznej.

Nie można tego kontrolować w MySQL przy użyciu WHEREskładni.

Quassnoi
źródło
10
Dzięki, Quassnoi. Masz wiele szczegółów w swoim ans; czy można uczciwie powiedzieć, że „tak, te zapytania są równoważne, ale należy użyć łączenia wewnętrznego, ponieważ jest bardziej czytelne i łatwiejsze do modyfikacji”?
allyourcode
8
@allyourcode: za Oracle, SQL Server, MySQLi PostgreSQL- tak. Prawdopodobnie w przypadku innych systemów, ale lepiej sprawdź.
Quassnoi
13
FWIW, używanie przecinków z warunkami łączenia w WHEREklauzuli jest również w standardzie ANSI.
Bill Karwin
1
@Bill Karwin: JOINsłowo kluczowe nie było częścią zastrzeżonych standardów do niedawna, jak mogłoby się wydawać. Przeszedł do Oraclewersji tylko 9i PostgreSQLwersji 7.2(obie wydane w 2001). Pojawienie się tego słowa kluczowego było częścią ANSIstandardowego przyjęcia i dlatego to słowo kluczowe jest zwykle kojarzone ANSI, mimo że to drugie obsługuje przecinek jako synonim CROSS JOIN.
Quassnoi
9
Niemniej jednak ANSI SQL-89 określił WHEREsprzężenia, które mają być wykonywane przecinkami i warunkami w klauzuli (bez warunków, łączenie jest równoważne łączeniu krzyżowemu, jak powiedziałeś). ANSI SQL-92 dodał JOINsłowo kluczowe i powiązaną składnię, ale składnia w stylu przecinka jest nadal obsługiwana dla kompatybilności wstecznej.
Bill Karwin
182

Inni zauważyli, że INNER JOINpomaga to czytelności dla ludzi, i to jest najwyższy priorytet, zgadzam się.
Pozwól, że wyjaśnię, dlaczego składnia łączenia jest bardziej czytelna.

Podstawowe SELECTzapytanie jest następujące:

SELECT stuff
FROM tables
WHERE conditions

SELECTKlauzula mówi nam co wracamy; FROMklauzula mówi nam, gdzie jesteśmy coraz to od, a WHEREklauzula mówi nam , które z nich dostajemy.

JOIN jest stwierdzeniem o tabelach, w jaki sposób są one powiązane (koncepcyjnie, w rzeczywistości, w jedną tabelę).

Wszelkie elementy zapytania, które kontrolują tabele - skąd otrzymujemy rzeczy - semantycznie należą do FROMklauzuli (i oczywiście tam JOINidą elementy). Umieszczenie elementów łączących w WHEREklauzuli łączy w sobie to, co i skąd , dlatego JOINpreferowana jest składnia.

Carl Manaster
źródło
7
Dziękujemy za wyjaśnienie, dlaczego preferowane jest połączenie wewnętrzne, Carl. Myślę, że twoja odpowiedź była ukryta w innych, ale jawna jest zwykle lepsza (tak, jestem fanem Pythona).
allyourcode
2
Semantyka ON i WHERE oznacza, że ​​dla DOŁĄCZENIA po ostatnim DOŁĄCZONYM ZEWNĘTRZNYM nie ma znaczenia, którego użyjesz. Chociaż cechujesz ON jako część JOIN, jest to również filtrowanie po produkcie kartezjańskim. Zarówno ON, jak i GDZIE filtrują produkt kartezjański. Ale przed ostatnim DOŁĄCZENIEM ZEWNĘTRZNYM należy użyć ON lub podselekcji z GDZIE . (ŁĄCZENIA nie są „włączone” parami kolumn. Dowolne dwie tabele można ŁĄCZYĆ W KAŻDYCH WARUNKACH. To tylko sposób na interpretację ŁĄCZNIKÓW W szczególności na równość kolumn.)
philipxy
Nawet jeśli użyjesz GDZIE do tego samego efektu INNER JOIN, wspomnisz dwie tabele w części FROM zapytania. Tak więc w zasadzie nadal sugerujesz, skąd bierzesz swoje dane w klauzuli FROM, więc chyba nie możesz powiedzieć, że „koniecznie łączy to, co i skąd”
cybergeek654
@ArsenKhachaturyan To, że słowo kluczowe lub identyfikator są używane w tekście, nie oznacza, że ​​jest to kod i wymaga formatu kodu. Jest to wybór formatowania, który może pójść w jakikolwiek sposób, a jeśli rozsądne jest edytowanie tutaj, uzasadnione jest ciągłe edytowanie każdego postu do innego formatu - to znaczy, że nie jest to uzasadnione. (Plus wbudowany format kodu na słowo może być trudny do odczytania.) To samo dotyczy podziałów akapitów tutaj - nie są one specjalnie wyjaśnione. To samo z „który” kontra „to”. Nazwy języków programowania nie powinny mieć formatu kodu. PS Błąd dodania podziału linii.
philipxy
@philipxy, jak wspomniałeś „to nie znaczy ...”, ale oczywiście nie oznacza to, że nie można go oznaczyć słowem kluczowym kodu. Tak, należy dokonać wyboru, ale wiele postów powstaje bez wiedzy o tym fakcie. Dlatego moja decyzja o wprowadzeniu zmian nie ma na celu zniszczenia niczego, ale uczynienie go bardziej czytelnym. Jeśli zauważyłeś jakąkolwiek przerwę po sformatowaniu zmian, przepraszam za to i oczywiście możesz cofnąć takie zmiany.
Arsen Khachaturyan
143

Stosowanie instrukcji warunkowych w ON / WHERE

Wyjaśniłem tutaj logiczne kroki przetwarzania zapytania.


Odniesienie: Wewnątrz Microsoft® SQL Server ™ 2005 Kwerenda T-SQL
Wydawca: Microsoft Press
Pub Data: 07 marca 2006
Drukuj ISBN-10: 0-7356-2313-9
Drukuj ISBN-13: 978-0-7356-2313-2
Strony: 640

Wewnątrz kwerendy T-SQL Microsoft® SQL Server ™ 2005

(8)  SELECT (9) DISTINCT (11) TOP <top_specification> <select_list>
(1)  FROM <left_table>
(3)       <join_type> JOIN <right_table>
(2)       ON <join_condition>
(4)  WHERE <where_condition>
(5)  GROUP BY <group_by_list>
(6)  WITH {CUBE | ROLLUP}
(7)  HAVING <having_condition>
(10) ORDER BY <order_by_list>

Pierwszym zauważalnym aspektem SQL innym niż inne języki programowania jest kolejność przetwarzania kodu. W większości języków programowania kod jest przetwarzany w kolejności, w jakiej został napisany. W SQL pierwszą przetwarzaną klauzulą ​​jest klauzula FROM, a klauzula SELECT, która pojawia się jako pierwsza, jest przetwarzana prawie na końcu.

Każdy krok generuje wirtualną tabelę, która jest używana jako dane wejściowe do następnego kroku. Te tabele wirtualne nie są dostępne dla osoby dzwoniącej (aplikacja kliencka lub zapytanie zewnętrzne). Tylko tabela wygenerowana przez ostatni krok jest zwracana do osoby dzwoniącej. Jeśli w zapytaniu nie podano określonej klauzuli, odpowiedni krok jest po prostu pomijany.

Krótki opis faz logicznego przetwarzania zapytania

Nie przejmuj się zbytnio, jeśli opis kroków wydaje się na razie bez sensu. Są one podane jako odniesienie. Sekcje, które pojawiają się po przykładzie scenariusza, będą omawiać kroki bardziej szczegółowo.

  1. FROM: Produkt kartezjański (łączenie krzyżowe) jest wykonywany między dwiema pierwszymi tabelami w klauzuli FROM, w wyniku czego generowana jest wirtualna tabela VT1.

  2. WŁ .: Filtr WŁ. Jest stosowany do VT1. Tylko wiersze, dla których <join_condition>jest PRAWDA, są wstawiane do VT2.

  3. ZEWNĘTRZNE (złączenie): Jeśli określono ZŁĄCZE ZEWNĘTRZNE (w przeciwieństwie do ZŁĄCZA KRZYŻOWEGO lub DOŁĄCZENIA WEWNĘTRZNEGO), wiersze z zachowanej tabeli lub tabel, dla których nie znaleziono dopasowania, są dodawane do wierszy z VT2 jako wiersze zewnętrzne, generując VT3. Jeśli w klauzuli FROM pojawiają się więcej niż dwie tabele, kroki od 1 do 3 są powtarzane między wynikiem ostatniego łączenia i następnej tabeli w klauzuli FROM, aż wszystkie tabele zostaną przetworzone.

  4. GDZIE: Filtr WHERE jest stosowany do VT3. Tylko wiersze, dla których <where_condition>jest PRAWDA, są wstawiane do VT4.

  5. GROUP BY: Wiersze z VT4 są ułożone w grupy na podstawie listy kolumn określonej w klauzuli GROUP BY. Generowane jest VT5.

  6. CUBE | ROLLUP: Supergrupy (grupy grup) są dodawane do wierszy z VT5, generując VT6.

  7. HAVING: Filtr HAVING jest stosowany do VT6. Tylko grupy, dla których <having_condition>jest PRAWDA, są wstawiane do VT7.

  8. SELECT: Lista SELECT jest przetwarzana, generując VT8.

  9. ODRÓŻNIJ: Zduplikowane wiersze są usuwane z VT8. VT9 jest generowany.

  10. ORDER BY: Wiersze z VT9 są sortowane zgodnie z listą kolumn określoną w klauzuli ORDER BY. Generowany jest kursor (VC10).

  11. TOP: Określona liczba lub procent wierszy jest wybierana od początku VC10. Tabela VT11 jest generowana i zwracana do osoby dzwoniącej.



Dlatego funkcja (WEJŚCIE DO WEJŚCIA) przefiltruje dane (sama liczba danych VT zostanie tutaj zmniejszona) przed zastosowaniem klauzuli WHERE. Kolejne warunki łączenia zostaną wykonane z przefiltrowanymi danymi, co poprawi wydajność. Następnie tylko warunek GDZIE zastosuje warunki filtru.

(Zastosowanie instrukcji warunkowych w ON / WHERE nie zrobi dużej różnicy w kilku przypadkach. Zależy to od liczby połączonych tabel i liczby wierszy dostępnych w każdej tabeli łączenia)

rafidheen
źródło
10
„Dlatego (INNER JOIN) ON przefiltruje dane (sama liczba danych VT zostanie tutaj zmniejszona) przed zastosowaniem klauzuli WHERE.” Niekoniecznie. Artykuł dotyczy logicznej kolejności przetwarzania. Kiedy mówisz, że konkretna implementacja zrobi jedną rzecz przed drugą, mówisz o zaimplementowanej kolejności przetwarzania. Implementacje mogą dokonywać dowolnych optymalizacji, o ile wynik jest taki sam, jak gdyby implementacja przebiegała zgodnie z logiczną kolejnością. Joe Celko wiele o tym napisał na Usenecie.
Mike Sherrill „Cat Recall”
@rafidheen "(INNER JOIN) ON filtruje dane ... przed zastosowaniem klauzuli WHERE ... co poprawia wydajność." Słuszna uwaga. „Po tym tylko warunek GDZIE zastosuje warunki filtru”. Co z klauzulą ​​HAVING?
James
@James To twierdzenie rafidheen jest błędne. Patrz „optymalizacja dołączania” w instrukcji. Również moje inne komentarze na tej stronie. (I MikeSherrill'CatRecall '). Takie „logiczne” opisy opisują wartość wyniku, a nie sposób jego obliczenia. I nie gwarantuje się, że takie zachowanie podczas wdrażania się nie zmieni.
philipxy
66

Domyślna składnia ANSI łączenia jest starsza, mniej oczywista i nie jest zalecana.

Ponadto algebra relacyjna umożliwia wymienność predykatów w WHEREklauzuli i INNER JOINtak, więc nawet INNER JOINzapytania z WHEREklauzulami mogą przestawiać predykaty przez optymalizator.

Polecam pisanie zapytań w możliwie najbardziej czytelny sposób.

Czasami obejmuje to uczynienie INNER JOINwzględnie „niekompletnym” i umieszczenie niektórych kryteriów w WHEREcelu ułatwienia zarządzania listami kryteriów filtrowania.

Na przykład zamiast:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

Pisać:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

Ale to oczywiście zależy.

Cade Roux
źródło
16
Twój pierwszy fragment zdecydowanie bardziej boli mój mózg. Czy ktoś to rzeczywiście robi? Jeśli spotkam kogoś, kto to robi, czy mogę go pokonać ponad głowę?
allyourcode
3
Lokalizuję kryteria tam, gdzie ma to największy sens. Jeśli dołączę do tymczasowo spójnej tabeli wyszukiwania migawek (i nie mam widoku ani funkcji UDF, która wymusza wybór prawidłowej daty), dołączę datę wejścia w życie do połączenia, a nie do GDZIE, ponieważ jest mniej prawdopodobnie przypadkowo zostanie usunięty.
Cade Roux,
14
@allyourcode: chociaż rzadko spotyka się tego typu składnię złączeń w ŁĄCZACH WEWNĘTRZNYCH, jest to dość powszechne w przypadku PRAWYCH ŁĄCZEŃ i LEWYCH ŁĄCZEŃ - określenie większej liczby szczegółów w predykacie łączenia eliminuje potrzebę podzapytania i zapobiega przypadkowemu odwróceniu złączeń zewnętrznych w WEJŚCIA WEWNĘTRZNE. (Chociaż zgadzam się, że dla INNER JOINs prawie zawsze wstawiałam c.State = 'NY' w klauzuli WHERE)
Dave Markle
1
@allyourcode Zdecydowanie to zrobię! Zgadzam się z Cade'em. Jestem ciekawy, czy istnieje jakiś dobry powód, aby tego nie
robić
31

Sprzężenia niejawne (tak zwane jest twoje pierwsze zapytanie) stają się znacznie bardziej mylące, trudne do odczytania i trudne do utrzymania, gdy zaczniesz dodawać kolejne tabele do zapytania. Wyobraź sobie, że wykonanie tego samego zapytania i typu łączenia na czterech lub pięciu różnych stołach ... to koszmar.

Używanie jawnego łączenia (twój drugi przykład) jest znacznie bardziej czytelne i łatwe w utrzymaniu.

matowy b
źródło
48
Nie mogłem się nie zgodzić. Składnia JOIN jest bardzo trudna i trudna do zorganizowania. Mam wiele zapytań łączących 5, 10, a nawet 15 tabel za pomocą łączenia klauzul WHERE i są one doskonale czytelne. Przepisanie takiego zapytania przy użyciu składni JOIN powoduje zniekształcenie. Co tylko pokazuje, że nie ma właściwej odpowiedzi na to pytanie i że zależy to bardziej od tego, z czym czujesz się komfortowo.
Noah Yetter
33
Noah, myślę, że możesz być tutaj w mniejszości.
matt b
2
Dostaję +1 do Matt i Noah. Lubię różnorodność :). Widzę, skąd pochodzi Noe; wewnętrzna złączenie nie dodaje nic nowego do języka i jest zdecydowanie bardziej szczegółowe. Z drugiej strony może sprawić, że stan „gdzie” będzie znacznie krótszy, co zwykle oznacza, że ​​jest łatwiejszy do odczytania.
allyourcode
5
Zakładam, że każdy rozsądny DBMS przetłumaczy dwa zapytania na ten sam plan wykonania; jednak w rzeczywistości każdy DBMS jest inny i jedynym sposobem, aby się upewnić, jest sprawdzenie planu wykonania (tj. trzeba go przetestować samodzielnie).
matt b
Czy to prawda, jak @rafidheen zasugerował w innej odpowiedzi (tej ze szczegółową sekwencją wykonywania SQL), że JOINy ​​są filtrowane pojedynczo, zmniejszając rozmiar operacji łączenia w porównaniu do pełnego kartezjańskiego łączenia 3 lub więcej tabel, z filtr GDZIE jest stosowany z mocą wsteczną? Jeśli tak, sugerowałoby to, że JOIN oferuje poprawę wydajności (a także zalety złączeń lewy / prawy, jak wskazano również w innej odpowiedzi).
James
26

Zaznaczę również, że stosowanie starszej składni jest bardziej podatne na błędy. Jeśli użyjesz sprzężenia wewnętrznego bez klauzuli ON, pojawi się błąd składniowy. Jeśli użyjesz starszej składni i zapomnisz o jednym z warunków łączenia w klauzuli where, otrzymasz sprzężenie krzyżowe. Programiści często naprawiają to, dodając wyraźne słowo kluczowe (zamiast naprawiać złączenie, ponieważ wciąż nie zdają sobie sprawy, że samo złączenie jest zepsute), które może wydawać się leczyć problem, ale znacznie spowalnia zapytanie.

Dodatkowo, jeśli chodzi o konserwację, jeśli masz sprzężenie krzyżowe w starej składni, skąd opiekun będzie wiedział, czy miałeś je mieć (są sytuacje, w których potrzebne są sprzężenia krzyżowe), czy też to powinien być wypadek?

Pozwól, że wskażę ci to pytanie, aby zobaczyć, dlaczego domyślna składnia jest zła, jeśli używasz lewych złączeń. Sybase * = do Ansi Standard z 2 różnymi zewnętrznymi stołami dla tego samego wewnętrznego stołu

Plus (tutaj osobisty rant), standard używający jawnych złączeń ma ponad 20 lat, co oznacza, że ​​domyślna składnia złączeń jest nieaktualna przez te 20 lat. Czy napiszesz kod aplikacji przy użyciu składni, która jest nieaktualna od 20 lat? Dlaczego chcesz napisać kod bazy danych?

HLGEM
źródło
3
@HLGEM: Chociaż całkowicie zgadzam się, że wyraźne JOIN są lepsze, zdarzają się przypadki, gdy musisz po prostu użyć starej składni. Przykład z prawdziwego świata: ANSI JOIN dostał się do Oracle tylko w wersji 9i, która została wydana w 2001 roku, i dopiero jeszcze rok temu (16 lat od momentu opublikowania standardu) musiałem wspierać kilka instalacji 8i, dla których mieliśmy wydać krytyczne aktualizacje. Nie chciałem utrzymywać dwóch zestawów aktualizacji, dlatego opracowaliśmy i przetestowaliśmy aktualizacje dla wszystkich baz danych, w tym 8i, co oznaczało, że nie byliśmy w stanie używać ANSI JOIN.
Quassnoi,
+1 interesujący punkt, gdy zauważysz, że sintax bez INNER JOIN jest bardziej podatny na błędy. Jestem zdezorientowany co do twojego ostatniego zdania, kiedy mówisz „... standard używający jawnych złączeń ma 17 lat”. więc sugerujesz użycie słowa kluczowego WEWNĘTRZNE ŁĄCZENIE, czy nie?
Marco Demaio,
1
@Marco Demaio, tak, zawsze używaj INNER JOIN lub JOIN (te dwa są takie same) lub LEFT JOIN lub RIGHT JOIN lub CROSS JOIN i nigdy nie używaj niejawnego łączenia przecinków.
HLGEM
2
„Dlaczego chcesz napisać kod bazy danych, który ma [20 lat]?” - Zauważam, że piszesz SQL, HAVINGktóry był „przestarzały”, odkąd SQL zaczął obsługiwać tabele pochodne. Zauważyłem również, że nie używasz, NATURAL JOINchociaż twierdzę, że stało się INNER JOIN„przestarzałe”. Tak, masz swoje powody (nie musisz ich tutaj ponownie podawać!): Chodzi mi o to, że ci, którzy lubią używać starszej składni, również mają swoje powody, a względny wiek składni ma niewielkie, jeśli w ogóle, znaczenie.
poniedziałek
1
GDZIE nadal jest w standardzie (pokaż mi, gdzie go nie ma). Więc najwyraźniej nic nie jest przestarzałe. Ponadto „zamiast naprawiać złączenie” pokazuje mi programistę, który powinien być trzymany z dala od DBMS w ogóle, daleko .
Jürgen A. Erhard
12

Mają inne znaczenie dla ludzi.

Jednak w zależności od optymalizatora zapytań mogą mieć to samo znaczenie dla komputera.

Należy zawsze kodować, aby był czytelny.

To znaczy, jeśli jest to wbudowana relacja, użyj jawnego łączenia. jeśli dopasowujesz słabo powiązane dane, użyj klauzuli where.

John Gietzen
źródło
11

Standard SQL: 2003 zmienił niektóre reguły pierwszeństwa, więc instrukcja JOIN ma pierwszeństwo przed złączeniem „przecinkiem”. To może faktycznie zmienić wyniki zapytania w zależności od jego konfiguracji. Powoduje to pewne problemy dla niektórych osób, gdy MySQL 5.0.12 przeszedł na przestrzeganie standardu.

W twoim przykładzie twoje zapytania działałyby tak samo. Ale jeśli dodałeś trzecią tabelę: WYBIERZ ... Z tabeli 1, tabela 2 DOŁĄCZ do tabeli 3 WŁ ... GDZIE ...

W wersjach wcześniejszych niż MySQL 5.0.12 najpierw dołączyła tabela 1 i tabela 2, a następnie tabela 3. Teraz (5.0.12 i nowsze) najpierw łączone są tabela 2 i tabela 3, a następnie tabela 1. Nie zawsze zmienia to wyniki, ale może i możesz nawet nie zdawać sobie z tego sprawy.

Nigdy nie używam już składni „przecinek”, wybierając drugi przykład. W każdym razie jest o wiele bardziej czytelny, warunki JOIN są z JOIN-ami, a nie oddzielnymi sekcjami zapytań.

Brent Baisley
źródło
Standardowy SQL nie zmienił się. MySQL był po prostu zły i teraz ma rację. Zobacz instrukcję MySQL.
philipxy
4

Wiem, że mówisz o MySQL, ale i tak: W Oracle 9 sprzężenia jawne i niejawne generowałyby różne plany wykonania. AFAIK, który został rozwiązany w Oracle 10+: nie ma już takiej różnicy.

João Marcus
źródło
1

Składnia złączenia ANSI jest zdecydowanie bardziej przenośna.

Przechodzę aktualizację Microsoft SQL Server, a także wspomnę, że składnia = * i * = dla sprzężeń zewnętrznych w SQL Server nie jest obsługiwana (bez trybu zgodności) dla serwera SQL 2005 i późniejszych.

Benzo
źródło
2
Nawet w SQL Server 2000, = i = mogą dawać błędne wyniki i nigdy nie powinny być używane.
HLGEM
2
*=i =*nigdy nie były ANSI i nigdy nie były dobrą notacją. Właśnie dlatego potrzebne było WŁĄCZENIE - dla ZEWNĘTRZNYCH DOŁĄCZNIKÓW przy braku podselekcji (które zostały dodane w tym samym czasie, więc nie są one tak naprawdę potrzebne w POŁĄCZENIACH KRZYŻOWYCH I WEWNĘTRZNYCH).
philipxy
1

Jeśli często programujesz dynamiczne procedury składowane, zakochasz się w drugim przykładzie (używając where). Jeśli masz różne parametry wejściowe i dużo bałaganu morfologicznego, to jest to jedyny sposób. W przeciwnym razie oba będą uruchamiać ten sam plan zapytań, więc zdecydowanie nie ma oczywistej różnicy w klasycznych zapytaniach.

Kviz Majster
źródło