2010-04-01 17 views
13

Jaka jest różnica międzyRóżnica między „a” i „gdzie” w dołącza

SELECT DISTINCT field1 
    FROM table1 cd 
    JOIN table2 
    ON  cd.Company = table2.Name 
     and table2.Id IN (2728) 

i

SELECT DISTINCT field1 
    FROM table1 cd 
    JOIN table2 
    ON cd.Company = table2.Name 
where table2.Id IN (2728) 

zwracają ten sam wynik i oba mają ten sam wyjaśnić wyświetlamy

+1

Mała wskazówka: zapoznaj się z planem wykonania, który może dać nieco więcej wglądu. SQL ma wiele optymalizacji zapytań. – Zyphrax

Odpowiedz

24

Po pierwsze jest różnica semantyczna. Kiedy masz połączenie, mówisz, że relacja między dwiema tabelami jest określona przez ten warunek. W pierwszym przykładzie mówisz, że tabele są powiązane przez cd.Company = table2.Name AND table2.Id IN (2728). Kiedy używasz klauzuli WHERE, mówisz, że relacja jest zdefiniowana przez cd.Company = table2.Name i że chcesz tylko wiersze, w których ma zastosowanie warunek table2.Id IN (2728). Mimo że dają one tę samą odpowiedź, oznacza to bardzo różne rzeczy dla programisty czytającego twój kod.

W tym przypadku klauzula WHERE prawie na pewno ma na myśli, więc należy jej użyć.

Po drugie, w rzeczywistości różnica polega na tym, że zamiast LINKI WEWNĘTRZNEJ używasz LEWEGO POŁĄCZENIA. Jeśli podasz drugi warunek w ramach łączenia, nadal otrzymasz wiersz wyniku, jeśli warunek się nie powiedzie - otrzymasz wartości z lewej tabeli i wartości zerowe dla prawej tabeli. Jeśli uwzględnisz warunek jako część klauzuli WHERE i ten warunek się nie powiedzie, nie otrzymasz całego wiersza.

Oto przykład, aby to pokazać.

Zapytanie 1 (gdzie)

SELECT DISTINCT field1 
    FROM table1 cd 
    LEFT JOIN table2 
    ON cd.Company = table2.Name 
WHERE table2.Id IN (2728); 

Wynik:

field1 
200 

Zapytanie 2 (I):

SELECT DISTINCT field1 
    FROM table1 cd 
    LEFT JOIN table2 
    ON cd.Company = table2.Name 
    AND table2.Id IN (2728); 

Wynik:

field1 
100 
200 

używane dane testowe:

CREATE TABLE table1 (Company NVARCHAR(100) NOT NULL, Field1 INT NOT NULL); 
INSERT INTO table1 (Company, Field1) VALUES 
('FooSoft', 100), 
('BarSoft', 200); 

CREATE TABLE table2 (Id INT NOT NULL, Name NVARCHAR(100) NOT NULL); 
INSERT INTO table2 (Id, Name) VALUES 
(2727, 'FooSoft'), 
(2728, 'BarSoft'); 
+1

+1 dla scenariusza "LEFT JOIN" – cjk

+0

+1 za podanie LEWEGO POŁĄCZENIA. nadal będę bezwstydnie wskazywać na moją odpowiedź http://stackoverflow.com/questions/2559194/difference-between-and-where-in-joins/2559769#2559769 na może jeszcze więcej szczegółów i powodów :) – Unreason

+0

W swoim przykład (zapytanie 2 z AND), jeśli mieliśmy table1.Id IN (100); nadal będzie zwracać dwa wiersze ... dlaczego to jest? ... – psj01

1

Nie nie ma różnicy. „ON” jest jak synonim „gdzie”, więc t on Drugi rodzaj brzmi następująco:

JOIN table2 WHERE cd.Company = table2.Name AND table2.Id IN (2728)

+0

Według http://dev.mysql.com/doc/refman/4.1/en/join.html nie wygląda na to, że ON jest synonimem WHERE. –

+2

Powiedziałem, że jest "jak" synonimem. –

+0

i tylko dla dołączeń joins.inner. – nawfal

3
  • Dołącz służy do odzwierciedlenia relacji encji
  • klauzuli WHERE filtruje w dół wyników .

Tak więc klauzule łączenia są "statyczne" (chyba że zmienia się stosunek encji),
, podczas gdy klauzule where są specyficzne dla użycia.

0

Nie ma różnicy, kiedy silnik optymalizacji zapytań rozbija go na odpowiednie operatory zapytań.

5

SQL pochodzi z relational algebra.

Jednym ze sposobów odróżnienia jest to, że DOŁĄCZY są operacjami na zestawach, które mogą wytworzyć więcej rekordów lub mniej rekordów w wyniku niż w oryginalnych tabelach. Z drugiej strony WHERE zawsze ogranicza liczbę wyników.

Dalsza część tekstu to dodatkowe wyjaśnienie.


Aby uzyskać więcej informacji na temat typów łączenia zobacz ponownie article.

Kiedy powiedziałem, że warunek "where" zawsze ogranicza wyniki, musisz wziąć pod uwagę, że kiedy mówimy o zapytaniach na dwóch (lub więcej) tabelach, musisz w jakiś sposób powiązać rekordy z tych tabel, nawet jeśli istnieje brak słowa kluczowego JOIN.

Tak więc w SQL, jeśli tabele są po prostu oddzielone przecinkiem, w rzeczywistości używasz CROSS JOIN (produkt kartezjański), który zwraca każdy wiersz z jednej tabeli dla każdego wiersza w drugim.

A ponieważ jest to maksymalna liczba kombinacji wierszy z dwóch tabel, wyniki dowolnego WHERE na tabelach połączonych krzyżowo mogą być wyrażone jako operacja JOIN.

Ale wstrzymaj się, są wyjątki od tego maksimum, gdy wprowadzisz sprzężenia LEFT, RIGHT i FULL OUTER.

LEFT JOIN dołącza rekordy z lewej tabeli do danego kryterium z rekordami z prawej tabeli, ALE jeśli kryteria łączenia, patrząc na wiersz z lewej tabeli nie jest spełniony dla jakichkolwiek rekordów w prawej tabeli LEWEJ JOIN nadal będzie zwracał rekord z lewej tabeli, a w kolumnach, które pochodzą z właściwej tabeli, zwróci wartości NULL (RIGHT JOIN działa podobnie, ale z drugiej strony FULL OUTER działa tak samo w tym samym czasie).

Ponieważ domyślne połączenie krzyżowe NIE zwraca tych rekordów, nie można wyrazić tych kryteriów sprzężenia za pomocą warunku WHERE i konieczne jest użycie składni JOIN (wyrostek był wyjątkiem od tego z rozszerzeniem do standardu SQL i to = operator, ale nie zostało to zaakceptowane przez innych sprzedawców ani standard).

Łączenia zwykle, ale nie zawsze, są zbieżne z istniejącą więzią referencyjną i sugerują relacje między podmiotami, ale nie przypisałbym temu tak dużej wagi, ponieważ warunki, w których warunki mogą być takie same (z wyjątkiem wcześniej wspomnianej sprawy) a do dobrego RDBMS nie ma znaczenia, gdzie określisz swoje kryteria.

+0

bardzo czyste wyjaśnienie – user187291

Powiązane problemy