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
?
sql
mysql
join
inner-join
JCCyC
źródło
źródło
Odpowiedzi:
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 JOIN
gdy zajdzie taka potrzeba.WHERE
Składnia jest bardziej zorientowany model relacyjny.Wynikiem dwóch tabel
JOIN
ed 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
WHERE
skł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_JOIN
klauzulę.Za pomocą tej klauzuli można kontrolować
JOIN
kolejność: 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
WHERE
składni.źródło
Oracle
,SQL Server
,MySQL
iPostgreSQL
- tak. Prawdopodobnie w przypadku innych systemów, ale lepiej sprawdź.WHERE
klauzuli jest również w standardzie ANSI.@Bill Karwin
:JOIN
słowo kluczowe nie było częścią zastrzeżonych standardów do niedawna, jak mogłoby się wydawać. Przeszedł doOracle
wersji tylko9
iPostgreSQL
wersji7.2
(obie wydane w2001
). Pojawienie się tego słowa kluczowego było częściąANSI
standardowego przyjęcia i dlatego to słowo kluczowe jest zwykle kojarzoneANSI
, mimo że to drugie obsługuje przecinek jako synonimCROSS JOIN
.WHERE
sprzęż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łJOIN
słowo kluczowe i powiązaną składnię, ale składnia w stylu przecinka jest nadal obsługiwana dla kompatybilności wstecznej.Inni zauważyli, że
INNER JOIN
pomaga 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
SELECT
zapytanie jest następujące:SELECT
Klauzula mówi nam co wracamy;FROM
klauzula mówi nam, gdzie jesteśmy coraz to od, aWHERE
klauzula 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
FROM
klauzuli (i oczywiście tamJOIN
idą elementy). Umieszczenie elementów łączących wWHERE
klauzuli łączy w sobie to, co i skąd , dlategoJOIN
preferowana jest składnia.źródło
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
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.
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.
WŁ .: Filtr WŁ. Jest stosowany do VT1. Tylko wiersze, dla których
<join_condition>
jest PRAWDA, są wstawiane do VT2.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.
GDZIE: Filtr WHERE jest stosowany do VT3. Tylko wiersze, dla których
<where_condition>
jest PRAWDA, są wstawiane do VT4.GROUP BY: Wiersze z VT4 są ułożone w grupy na podstawie listy kolumn określonej w klauzuli GROUP BY. Generowane jest VT5.
CUBE | ROLLUP: Supergrupy (grupy grup) są dodawane do wierszy z VT5, generując VT6.
HAVING: Filtr HAVING jest stosowany do VT6. Tylko grupy, dla których
<having_condition>
jest PRAWDA, są wstawiane do VT7.SELECT: Lista SELECT jest przetwarzana, generując VT8.
ODRÓŻNIJ: Zduplikowane wiersze są usuwane z VT8. VT9 jest generowany.
ORDER BY: Wiersze z VT9 są sortowane zgodnie z listą kolumn określoną w klauzuli ORDER BY. Generowany jest kursor (VC10).
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)
źródło
Domyślna składnia ANSI łączenia jest starsza, mniej oczywista i nie jest zalecana.
Ponadto algebra relacyjna umożliwia wymienność predykatów w
WHERE
klauzuli iINNER JOIN
tak, więc nawetINNER JOIN
zapytania zWHERE
klauzulami mogą przestawiać predykaty przez optymalizator.Polecam pisanie zapytań w możliwie najbardziej czytelny sposób.
Czasami obejmuje to uczynienie
INNER JOIN
względnie „niekompletnym” i umieszczenie niektórych kryteriów wWHERE
celu ułatwienia zarządzania listami kryteriów filtrowania.Na przykład zamiast:
Pisać:
Ale to oczywiście zależy.
źródło
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.
źródło
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?
źródło
HAVING
który był „przestarzały”, odkąd SQL zaczął obsługiwać tabele pochodne. Zauważyłem również, że nie używasz,NATURAL JOIN
chociaż 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.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.
źródło
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ń.
źródło
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.
źródło
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.
źródło
*=
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).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.
źródło