Po przeczytaniu go, to nie duplikat Explicit vs niejawny SQL przyłącza . Odpowiedź może być powiązana (lub nawet taka sama), ale pytanie jest inne.
Jaka jest różnica i co powinno się w nich znaleźć?
Jeśli dobrze rozumiem teorię, optymalizator zapytań powinien być w stanie używać obu zamiennie.
Odpowiedzi:
To nie to samo.
Rozważ te zapytania:
i
Pierwszy zwróci zamówienie i jego ewentualne wiersze dla numeru zamówienia
12345
. Drugi zwróci wszystkie zamówienia, ale tylko zamówienie12345
będzie miało powiązane linie.W przypadku
INNER JOIN
klauzule są faktycznie równoważne. Jednak tylko dlatego, że są funkcjonalnie takie same, ponieważ dają takie same wyniki, nie oznacza, że dwa rodzaje klauzul mają to samo znaczenie semantyczne.źródło
Sprawy dla połączeń zewnętrznych
za.
WHERE
klauzula: Po dołączeniu. Rekordy zostaną odfiltrowane po zakończeniu łączenia.b.
ON
klauzula - Przed dołączeniem. Rekordy (z prawej tabeli) będą filtrowane przed dołączeniem. Wynik może być zerowy (od przyłączenia OUTER).Przykład : Rozważ poniższe tabele:
a)
WHERE
Klauzula wewnętrzna :b)
JOIN
Klauzula wewnętrznaźródło
intermediate join table
? Jakieś polecenie „Wyjaśnij”?Na
INNER JOIN
s są wymienne i optymalizator zmienić ich woli.W przypadku
OUTER JOIN
s niekoniecznie są one zamienne, w zależności od strony połączenia, od której zależą.Umieszczam je w dowolnym miejscu w zależności od czytelności.
źródło
Orders.Join( OrderLines, x => x.ID, x => OrderID, (o,l) => new {Orders = o, Lines = l}).Where( ol => ol.Orders.ID = 12345)
Tak to robię:
Zawsze umieszczaj warunki łączenia w
ON
klauzuli, jeśli wykonujeszINNER JOIN
. Dlatego nie dodawaj żadnych warunków GDZIE do klauzuli ON, umieść je wWHERE
klauzuli.Jeśli wykonujesz a
LEFT JOIN
, dodaj dowolne warunki WHERE doON
klauzuli dotyczącej tabeli po prawej stronie złączenia. Jest to konieczne, ponieważ dodanie klauzuli WHERE, która odwołuje się do prawej strony złączenia, przekształci złączenie w INNER JOIN.Wyjątkiem jest sytuacja, gdy szukasz rekordów, które nie znajdują się w określonej tabeli. Można by dodać odwołanie do unikalnego identyfikatora (który nie jest nigdy NULL) w prawym JOIN tabeli klauzuli WHERE w następujący sposób:
WHERE t2.idfield IS NULL
. Tak więc jedyny raz, kiedy powinieneś odwołać się do tabeli po prawej stronie złączenia, jest znalezienie tych rekordów, których nie ma w tabeli.źródło
W połączeniu wewnętrznym oznaczają to samo. Jednak uzyskasz różne wyniki w złączeniu zewnętrznym, w zależności od tego, czy umieścisz warunek złączenia w klauzuli WHERE vs ON. Spójrz na to powiązane pytanie i tę odpowiedź (przeze mnie).
Myślę, że najbardziej sensowne jest przyzwyczajenie się do umieszczania warunku łączenia w klauzuli ON (chyba że jest to łączenie zewnętrzne, a tak naprawdę chcesz tego w klauzuli where), ponieważ czyni to bardziej zrozumiałym dla każdego, kto czyta twoje zapytanie w jakich warunkach łączone są tabele, a także pomaga to, aby klauzula WHERE nie miała kilkudziesięciu wierszy.
źródło
Relacja tabeli
Biorąc pod uwagę, że mamy następujące
post
ipost_comment
tabele:post
Ma następujące zapisy:i
post_comment
ma następujące trzy rzędy:DOŁĄCZ DO WEWNĘTRZNEGO SQL
Klauzula JOIN SQL umożliwia powiązanie wierszy należących do różnych tabel. Na przykład CROSS JOIN utworzy produkt kartezjański zawierający wszystkie możliwe kombinacje wierszy między dwiema tabelami łączenia.
Chociaż połączenie krzyżowe jest przydatne w niektórych scenariuszach, w większości przypadków chcesz łączyć tabele w oparciu o określony warunek. I tu właśnie wchodzi INNER JOIN.
SQL INNER JOIN pozwala nam filtrować produkt kartezjański łączenia dwóch tabel w oparciu o warunek określony za pomocą klauzuli ON.
DOŁĄCZ DO WEWNĘTRZNEGO SQL - W stanie „zawsze prawdziwa”
Jeśli podasz warunek „zawsze prawda”, ŁĄCZENIE WEWNĘTRZNE nie będzie filtrowało połączonych rekordów, a zestaw wyników będzie zawierał iloczyn kartezjański dwóch tabel łączących.
Na przykład, jeśli wykonamy następujące zapytanie SQL INNER JOIN:
Otrzymamy wszystkie kombinacje
post
ipost_comment
rekordy:Jeśli więc warunek klauzuli ON jest „zawsze prawdziwy”, INNER JOIN jest po prostu równoważne zapytaniu CROSS JOIN:
DOŁĄCZ DO WEWNĘTRZNEGO SQL - W stanie „zawsze fałszywe”
Z drugiej strony, jeśli warunek klauzuli ON jest „zawsze fałszywy”, wówczas wszystkie połączone rekordy zostaną odfiltrowane, a zestaw wyników będzie pusty.
Jeśli więc wykonamy następujące zapytanie SQL INNER JOIN:
Nie otrzymamy żadnego wyniku z powrotem:
Dzieje się tak, ponieważ powyższe zapytanie jest równoważne następującemu zapytaniu CROSS JOIN:
SQL INNER JOIN - ON klauzula przy użyciu kolumn klucza obcego i klucza podstawowego
Najczęstszym warunkiem klauzuli ON jest ten, który pasuje do kolumny Klucz obcy w tabeli podrzędnej z kolumną Klucz główny w tabeli nadrzędnej, co ilustruje następujące zapytanie:
Podczas wykonywania powyższego zapytania SQL INNER JOIN otrzymujemy następujący zestaw wyników:
Tak więc tylko rekordy spełniające warunek klauzuli ON są zawarte w zestawie wyników zapytania. W naszym przypadku zestaw wyników zawiera wszystkie dane
post
wraz z ichpost_comment
rekordami. Tepost
wiersze, które nie związanepost_comment
są wyłączone, ponieważ nie może spełniać warunek ON klauzuli.Ponownie powyższe zapytanie SQL INNER JOIN jest równoważne następującemu zapytaniu CROSS JOIN:
Nieprzestrzegane wiersze są tymi, które spełniają klauzulę WHERE i tylko te rekordy zostaną uwzględnione w zestawie wyników. To najlepszy sposób na wizualizację działania klauzuli INNER JOIN.
Wniosek
Instrukcja INNER JOIN może zostać przepisana jako CROSS JOIN z klauzulą WHERE pasującą do tego samego warunku, którego użyto w klauzuli ON zapytania INNER JOIN.
źródło
Istnieje wielka różnica między klauzulą where a klauzulą , jeśli chodzi o lewe łączenie.
Oto przykład:
Tam jest identyfikator tabeli t2.
Zapytanie o klauzulę „on”:
Zapytanie dotyczące „klauzuli gdzie”:
Oczywiste jest, że pierwsze zapytanie zwraca rekord z t1 i jego zależny wiersz z t2, jeśli istnieje, dla wiersza t1.v = „K”.
Drugie zapytanie zwraca wiersze z t1, ale tylko dla t1.v = „K” będzie z nim powiązany dowolny wiersz.
źródło
Jeśli chodzi o optymalizator, nie powinno mieć znaczenia, czy definiujesz klauzule łączenia za pomocą ON czy WHERE.
Jednak, IMHO, myślę, że o wiele łatwiej jest użyć klauzuli ON podczas wykonywania złączeń. W ten sposób masz określoną sekcję zapytania, która określa, jak obsługiwane jest łączenie w porównaniu z pozostałymi częściami klauzul WHERE.
źródło
Rozważmy te tabele:
ZA
b
id_A
będąc kluczem obcym do tabeliA
Pisanie tego zapytania:
Zapewni ten wynik:
To, co jest w A, ale nie w B, oznacza, że dla B. istnieją wartości zerowe.
Teraz rozważmy konkretną część
B.id_A
i podkreślmy ją z poprzedniego wyniku:Pisanie tego zapytania:
Zapewni ten wynik:
Ponieważ powoduje to usunięcie sprzężenia wewnętrznego wartości, których nie ma
B.id_A = SpecificPart
Teraz zmieńmy zapytanie na to:
Wynik jest teraz:
Ponieważ cały wynik jest filtrowany przed
B.id_A = SpecificPart
usunięciem częściB.id_A = NULL
znajdujących się w A, które nie są w Bźródło
Czy próbujesz dołączyć dane lub filtrować dane?
Dla czytelności najbardziej sensowne jest izolowanie tych przypadków użycia odpowiednio na ON i WHERE.
Bardzo trudno odczytać zapytanie, w którym warunek JOIN i warunek filtrowania istnieją w klauzuli WHERE.
Jeśli chodzi o wydajność, nie powinieneś widzieć różnicy, chociaż różne typy SQL czasami obsługują planowanie zapytań inaczej, więc warto spróbować
¯\_(ツ)_/¯
(pamiętaj, że buforowanie wpływa na szybkość zapytań)Również, jak zauważyli inni, jeśli użyjesz sprzężenia zewnętrznego, uzyskasz inne wyniki, jeśli umieścisz warunek filtru w klauzuli ON, ponieważ wpływa on tylko na jedną z tabel.
Bardziej szczegółowy post napisałem o tym tutaj: https://dataschool.com/learn/difference-between-where-and-on-in-sql
źródło
W SQL klauzule „WHERE” i „ON” są rodzajem warunkowych instrukcji, ale główna różnica między nimi polega na tym, że klauzula „Where” jest używana w instrukcjach Select / Update do określania warunków, natomiast klauzula „ON” jest używany w połączeniach, gdzie weryfikuje lub sprawdza, czy rekordy są dopasowane w tabelach docelowych i źródłowych, przed dołączeniem tabel
Na przykład: - „GDZIE”
Na przykład: - „ON”
Istnieją dwie tabele pracownik i szczegółowe informacje o pracowniku, pasujące kolumny to identyfikator pracownika.
Mam nadzieję, że odpowiedziałem na twoje pytanie. Powróć do wszelkich wyjaśnień.
źródło
WHERE
zamiastON
, prawda? sqlfiddle.com/#!2/ae5b0/14/0Myślę, że to efekt sekwencji łączenia. W przypadku lewego górnego przypadku łączenia najpierw SQL wykonaj lewe połączenie, a następnie wykonaj filtr gdzie. W niższym przypadku najpierw znajdź Orders.ID = 12345, a następnie dołącz.
źródło
Do łączenia wewnętrznego
WHERE
iON
może być używany zamiennie. W rzeczywistości możliwe jest użycieON
w skorelowanym podzapytaniu. Na przykład:Jest to (IMHO) całkowicie mylące dla człowieka i bardzo łatwo jest zapomnieć o linkowaniu
table1
do czegokolwiek (ponieważ tabela „sterownika” nie ma klauzuli „on”), ale jest legalna.źródło
w celu uzyskania lepszej wydajności tabele powinny mieć specjalną indeksowaną kolumnę do użycia dla JOINS.
więc jeśli kolumna, na której warunkujesz, nie jest jedną z tych indeksowanych kolumn, podejrzewam, że lepiej trzymać ją w GDZIE.
więc ŁĄCZYCIE za pomocą indeksowanych kolumn, a następnie po ŁĄCZENIU uruchamiasz warunek w kolumnie nieindeksowanej.
źródło
Zwykle filtrowanie jest przetwarzane w klauzuli WHERE po połączeniu dwóch tabel. Możliwe jest jednak, że możesz chcieć przefiltrować jedną lub obie tabele przed dołączeniem do nich. tzn. klauzula where ma zastosowanie do całego zestawu wyników, podczas gdy klauzula on ma zastosowanie tylko do danego sprzężenia.
źródło
Myślę, że to rozróżnienie można najlepiej wyjaśnić poprzez logiczną kolejność operacji w SQL , co jest uproszczone:
FROM
(w tym dołączenia)WHERE
GROUP BY
HAVING
WINDOW
SELECT
DISTINCT
UNION
,INTERSECT
,EXCEPT
ORDER BY
OFFSET
FETCH
Połączenia nie są klauzulą instrukcji select, ale operatorem wewnątrz
FROM
. Jako takie, wszystkieON
klauzule należące do odpowiedniegoJOIN
operatora „już się zdarzyły” logicznie , zanim przetwarzanie logiczne osiągnieWHERE
klauzulę. Oznacza to, że w przypadkuLEFT JOIN
, na przykład, semantyka sprzężenia zewnętrznego już się zdarzyła do czasuWHERE
klauzuli.Bardziej szczegółowo wyjaśniłem następujący przykład w tym poście na blogu . Podczas uruchamiania tego zapytania:
To
LEFT JOIN
naprawdę nie ma żadnego użytecznego efektu, ponieważ nawet jeśli aktor nie grał w filmie, aktor zostanie przefiltrowany, tak jakFILM_ID
będzie,NULL
aWHERE
klauzula przefiltruje taki wiersz. Wynikiem jest coś takiego:To znaczy tak, jakbyśmy połączyli dwa stoliki. Jeśli przeniesiemy predykat filtru w
ON
klauzuli, stanie się on teraz kryterium dla sprzężenia zewnętrznego:Oznacza to, że wynik będzie zawierać aktorów bez filmów lub bez filmów z
FILM_ID < 10
W skrócie
Logicznie zawsze umieszczaj predykat tam, gdzie ma to sens.
źródło
Jeśli chodzi o twoje pytanie,
Jest to to samo zarówno „na”, jak i „gdzie” na złączeniu wewnętrznym, o ile serwer może to uzyskać:
i
Opcji „gdzie” nie wszyscy tłumacze znają, więc należy unikać. I oczywiście klauzula włączenia jest jaśniejsza.
źródło
to jest moje rozwiązanie.
Państwo musi mieć
GROUP BY
aby zmusić go do pracy.Mam nadzieję, że to pomoże.
źródło