W zapytaniach MySQL, po co używać join zamiast gdzie?


109

Wygląda na to, że łączymy dwa lub więcej tabel, możemy użyć złączenia lub gdzie. Jakie są zalety jednego nad drugim?


2
W zależności od zastosowania może mieć takie same wyniki, ale za pomocą JOIN możesz tworzyć inne rodzaje skojarzeń.
zneak

Czy to odpowiada na twoje pytanie? Klauzula INNER JOIN ON vs WHERE
philipxy

Odpowiedzi:


161

Każde zapytanie obejmujące więcej niż jedną tabelę wymaga jakiejś formy powiązania w celu połączenia wyników z tabeli „A” z tabelą „B”. Tradycyjny sposób (ANSI-89) to:

  1. Wypisz tabele biorące udział w liście oddzielonej przecinkami w klauzuli FROM
  2. Zapisz powiązanie między tabelami w klauzuli WHERE

    SELECT *
      FROM TABLE_A a,
           TABLE_B b
     WHERE a.id = b.id

Oto zapytanie przepisane przy użyciu składni ANSI-92 JOIN:

SELECT *
  FROM TABLE_A a
  JOIN TABLE_B b ON b.id = a.id

Z perspektywy wydajności:


Tam, gdzie jest obsługiwana (Oracle 9i +, PostgreSQL 7.2+, MySQL 3.23+, SQL Server 2000+), używanie obu składni nie daje korzyści w zakresie wydajności. Optymalizator widzi je jako to samo zapytanie. Jednak bardziej złożone zapytania mogą skorzystać ze składni ANSI-92:

  • Możliwość kontrolowania kolejności JOIN - kolejności skanowania tabel
  • Możliwość zastosowania kryteriów filtrowania do tabeli przed dołączeniem

Z perspektywy konserwacji:


Istnieje wiele powodów, dla których warto używać składni ANSI-92 JOIN zamiast ANSI-89:

  • Bardziej czytelne, ponieważ kryteria JOIN są oddzielone od klauzuli WHERE
  • Rzadziej przegapisz kryteria JOIN
  • Spójna obsługa składni dla typów JOIN innych niż INNER, dzięki czemu zapytania są łatwe w użyciu w innych bazach danych
  • Klauzula WHERE służy tylko jako filtracja iloczynu kartezjańskiego połączonych tabel

Z perspektywy projektu:


Składnia ANSI-92 JOIN jest wzorcem, a nie anty-wzorcem:

  • Cel zapytania jest bardziej oczywisty; kolumny używane przez aplikację są jasne
  • Jest zgodny z zasadą modułowości dotyczącą używania ścisłego pisania, gdy tylko jest to możliwe. Wyraźne jest prawie powszechnie lepsze.

Wniosek


Poza znajomością i / lub komfortem, nie widzę żadnej korzyści z dalszego używania klauzuli ANSI-89 WHERE zamiast składni ANSI-92 JOIN. Niektórzy mogą narzekać, że składnia ANSI-92 jest bardziej szczegółowa, ale to właśnie czyni to jednoznacznym. Im bardziej wyraźne, tym łatwiejsze do zrozumienia i utrzymania.


14
„... Każde zapytanie obejmujące więcej niż jedną tabelę wymaga jakiejś formy asocjacji, aby połączyć wyniki z tabeli„ A ”z tabelą„ B ”… W przeciwnym razie otrzymasz iloczyn kartezjański, a prawdopodobnie tego nie chcesz (ci Kartezjanie robią LOUSY produkty)
Scott Smith,

8

Większość ludzi uważa, że ​​składnia JOIN jest nieco bardziej przejrzysta, jeśli chodzi o to, co jest łączone z czym. Dodatkowo ma tę zaletę, że jest standardem.

Osobiście „dorastałem” na WHEREs, ale im częściej używam składni JOIN, tym bardziej zaczynam rozumieć, że jest to bardziej przejrzyste.


1
@nawfal Rozumiem - wychowałem się na składni w starym stylu, ale kiedy przyzwyczaiłem się do nowej, korzyści stały się jasne, np. trudniej zrobić połączenie krzyżowe przez pomyłkę, bardziej wyraźne, łatwiejsze do zobaczenia, co to jest złączenie i co jest filtr itp ... wciągnęło mnie.
Podstawowy

8

Oto problemy związane ze stosowaniem składni where (inaczej zwanej niejawnym złączeniem):

Po pierwsze, uzyskanie przypadkowych sprzężeń krzyżowych jest zbyt łatwe, ponieważ warunki łączenia nie znajdują się tuż obok nazw tabel. Jeśli masz 6 połączonych tabel, łatwo przeoczyć jeden w klauzuli where. Zbyt często będzie to naprawiane za pomocą odrębnego słowa kluczowego. To olbrzymi spadek wydajności bazy danych. Nie można uzyskać przypadkowego sprzężenia krzyżowego przy użyciu jawnej składni łączenia, ponieważ nie powiedzie się sprawdzania składni.

Łączenia prawe i lewe są problematyczne (na serwerze SQl nie ma gwarancji uzyskania poprawnych wyników) w starej składni w niektórych bazach danych. Ponadto są przestarzałe w SQL Server, które znam.

Jeśli zamierzasz użyć sprzężenia krzyżowego, nie wynika to jasno ze starej składni. Jest to jasne przy użyciu obecnego standardu ANSII.

Opiekunowi znacznie trudniej jest zobaczyć, które dokładnie pola są częścią łączenia, a nawet które tabele łączą się w jakiej kolejności, używając niejawnej składni. Oznacza to, że weryfikacja zapytań może zająć więcej czasu. Znałem bardzo niewielu ludzi, którzy kiedyś, gdy poczuli się komfortowo z jawną składnią dołączania, kiedykolwiek wrócili do starego sposobu.

Zauważyłem również, że niektórzy ludzie, którzy używają tych niejawnych złączeń, tak naprawdę nie rozumieją, jak działają złączenia i dlatego uzyskują nieprawidłowe wyniki w swoich zapytaniach.

Szczerze mówiąc, czy użyłbyś innego rodzaju kodu, który został zastąpiony lepszą metodą 18 lat temu?


6

Jawne sprzężenia przekazują zamiar, pozostawiając klauzulę where do wykonania filtrowania. Jest czystszy i jest standardem, a możesz robić takie rzeczy, jak lewy zewnętrzny lub prawy zewnętrzny, co jest trudniejsze do zrobienia tylko gdzie.


3

Nie możesz użyć GDZIE, aby połączyć dwie tabele. Możesz jednak napisać:

SELECT * FROM A, B
WHERE ...

Przecinek tutaj jest odpowiednikiem pisania:

SELECT *
FROM A
CROSS JOIN B
WHERE ...

Napisałbyś to? Nie - bo wcale nie o to ci chodzi. Nie chcesz łączenia krzyżowego, chcesz WEWNĘTRZNEGO POŁĄCZENIA. Ale kiedy piszesz przecinek, mówisz CROSS JOIN i to jest mylące.


0

Właściwie często potrzebujesz zarówno „GDZIE”, jak i „DOŁĄCZ”.

„JOIN” służy do pobierania danych z dwóch tabel - na podstawie wartości wspólnej kolumny. Jeśli chcesz dalej filtrować ten wynik, użyj klauzuli WHERE.

Na przykład „LEFT JOIN” pobiera WSZYSTKIE wiersze z lewej tabeli oraz pasujące wiersze z prawej tabeli. Ale to nie filtruje rekordów pod kątem żadnej określonej wartości ani innych kolumn, które nie są częścią JOIN. Dlatego jeśli chcesz dalej filtrować ten wynik, określ dodatkowe filtry w klauzuli WHERE.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.