Także jak zrobić LEFT JOIN
, RIGHT JOIN
i FULL JOIN
zmieścić się w?
Także jak zrobić LEFT JOIN
, RIGHT JOIN
i FULL JOIN
zmieścić się w?
Odpowiedzi:
Zakładając, że dołączasz do kolumn bez duplikatów, co jest bardzo częstym przypadkiem:
Połączenie wewnętrzne A i B daje wynik przecięcia A, tj. Wewnętrznej części przecięcia diagramu Venna .
Zewnętrzne połączenie A i B daje wyniki połączenia A, tj. Zewnętrzne części połączenia diagramu Venna.
Przykłady
Załóżmy, że masz dwie tabele, każda z jedną kolumną i dane w następujący sposób:
A B
- -
1 3
2 4
3 5
4 6
Należy zauważyć, że (1,2) są unikalne dla A, (3,4) są wspólne, a (5,6) są unikalne dla B.
Wewnętrzne dołączenie
Połączenie wewnętrzne za pomocą jednego z równoważnych zapytań daje przecięcie dwóch tabel, tj. Dwóch wierszy, które mają ze sobą wspólne.
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
a | b
--+--
3 | 3
4 | 4
Lewe zewnętrzne połączenie
Lewe sprzężenie zewnętrzne da wszystkie rzędy w A plus wszystkie wspólne rzędy w B.
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
Prawe połączenie zewnętrzne
Prawe połączenie zewnętrzne da wszystkie rzędy w B plus wszystkie wspólne rzędy w A.
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
Pełne połączenie zewnętrzne
Pełne sprzężenie zewnętrzne da ci połączenie A i B, tj. Wszystkie wiersze w A i wszystkie wiersze w B. Jeśli coś w A nie ma odpowiadającego układu odniesienia w B, wówczas część B jest zerowa i odwrotnie versa.
select * from a FULL OUTER JOIN b on a.a = b.b;
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
Diagramy Venna tak naprawdę nie robią tego dla mnie.
Nie wykazują one na przykład żadnego rozróżnienia między połączeniem krzyżowym a łączeniem wewnętrznym, lub bardziej ogólnie pokazują jakiekolwiek rozróżnienie między różnymi typami predykatów łączenia lub zapewniają ramy dla uzasadnienia sposobu, w jaki będą działać.
Nie ma substytutu dla zrozumienia logicznego przetwarzania, a jego zrozumienie jest stosunkowo proste.
on
klauzulę względem wszystkich wierszy z kroku 1, zachowując te, do których predykat oceniatrue
(Uwaga: w praktyce optymalizator zapytań może znaleźć bardziej wydajne sposoby wykonania zapytania niż czysto logiczny opis powyżej, ale ostateczny wynik musi być taki sam)
Zacznę od animowanej wersji pełnego sprzężenia zewnętrznego . Dalsze wyjaśnienie następuje.
Tabele źródłowe
Najpierw zacznij od CROSS JOIN
(produktu kartezjańskiego AKA). To nie ma ON
klauzuli i po prostu zwraca każdą kombinację wierszy z dwóch tabel.
WYBIERZ A.KOLOR, B.KOLOR Z KRZYŻA DOŁĄCZ B
Złączenia wewnętrzne i zewnętrzne mają predykat „ON”.
WYBIERZ A.KOLOR, B.KOLOR OD WEWNĘTRZNEGO DOŁĄCZENIA B NA A.KOLOR = B.KOLOR
Powyżej jest klasyczne połączenie equi.
Wewnętrzny warunek łączenia niekoniecznie musi być warunkiem równości i nie musi odwoływać się do kolumn z obu (lub nawet obu) tabel. Ocena A.Colour NOT IN ('Green','Blue')
w każdym wierszu sprzężenia krzyżowego zwraca wartość.
WYBIERZ A.KOLOR, B.KOLOR OD WEWNĘTRZNEJ DOŁĄCZ DO B 1 = 1
Warunek łączenia ma wartość true dla wszystkich wierszy w wyniku połączenia krzyżowego, więc jest to to samo, co połączenie krzyżowe. Nie powtórzę już obrazu 16 rzędów.
Połączenia zewnętrzne są logicznie oceniane w taki sam sposób, jak połączenia wewnętrzne, z tym wyjątkiem, że jeśli wiersz z lewej tabeli (dla lewego łączenia) nie łączy się z żadnymi wierszami z prawej tabeli, zostaje zachowany w wyniku z NULL
wartościami dla kolumny po prawej stronie.
To po prostu ogranicza poprzedni wynik, aby zwracał tylko wiersze, w których B.Colour IS NULL
. W tym konkretnym przypadku będą to wiersze, które zostały zachowane, ponieważ nie pasowały do tabeli po prawej stronie, a zapytanie zwraca pojedynczy czerwony wiersz niepasujący do tabeli B
. Jest to znane jako anty-semi-join.
Ważne jest, aby wybrać do IS NULL
testu kolumnę, która albo nie ma wartości zerowej, albo dla której warunek łączenia gwarantuje, że wszelkie NULL
wartości zostaną wykluczone, aby ten wzorzec działał poprawnie i unikał po prostu przywracania wierszy, które mają taką NULL
wartość kolumna oprócz niepasujących wierszy.
Prawe połączenia zewnętrzne działają podobnie jak lewe połączenia zewnętrzne, z tym wyjątkiem, że zachowują niepasujące wiersze z prawej tabeli i zerują przedłużenie lewej kolumny.
Pełne sprzężenia zewnętrzne łączą zachowanie złączeń lewego i prawego i zachowują niepasujące wiersze z lewej i prawej tabeli.
Żadne wiersze w łączeniu krzyżowym nie pasują do 1=0
predykatu. Wszystkie wiersze z obu stron są zachowywane przy użyciu normalnych reguł łączenia zewnętrznego o wartości NULL w kolumnach tabeli po drugiej stronie.
Po niewielkiej zmianie poprzedniego zapytania można symulować jedną UNION ALL
z dwóch tabel.
Zauważ, że WHERE
klauzula (jeśli jest obecna) logicznie działa po złączeniu. Jednym z powszechnych błędów jest wykonanie lewego łączenia zewnętrznego, a następnie dołączenie klauzuli WHERE z warunkiem w prawej tabeli, która kończy się wykluczeniem niepasujących wierszy. Powyżej kończy się łączenie zewnętrzne ...
... A potem działa klauzula „Where”. NULL= 'Green'
nie sprawdza się jako prawda, więc rząd zachowany przez połączenie zewnętrzne zostaje ostatecznie odrzucony (wraz z niebieskim), skutecznie przekształcając połączenie z powrotem w wewnętrzny.
Jeśli intencją było uwzględnienie tylko wierszy z B, gdzie Kolor jest Zielony, i wszystkich wierszy z A, niezależnie od tego, jaka byłaby poprawna składnia
Zobacz te przykłady uruchomione na żywo w SQLFiddle.com .
Łączy są wykorzystywane do łączenia danych z dwóch tabel, w związku z czym nowa, tymczasowa tabela. Połączenia są wykonywane na podstawie czegoś zwanego predykatem, który określa warunek do użycia w celu wykonania połączenia. Różnica między złączeniem wewnętrznym a złączem zewnętrznym polega na tym, że połączenie wewnętrzne zwróci tylko wiersze, które faktycznie pasują na podstawie predykatu łączenia. Na przykład: Rozważmy tabelę pracownika i lokalizacji:
Łączenie wewnętrzne : - Łączenie wewnętrzne tworzy nową tabelę wyników, łącząc wartości kolumn dwóch tabel ( pracownika i lokalizacji ) na podstawie predykatu łączenia. Zapytanie porównuje każdy wiersz pracownika z każdym wierszem lokalizacji, aby znaleźć wszystkie pary wierszy spełniające predykat łączenia. Gdy predykat łączenia jest spełniony przez dopasowanie wartości innych niż NULL, wartości kolumn dla każdej dopasowanej pary wierszy pracownika i lokalizacji są łączone w wiersz wynikowy. Oto jak będzie wyglądał SQL dla sprzężenia wewnętrznego:
select * from employee inner join location on employee.empID = location.empID
OR
select * from employee, location where employee.empID = location.empID
Oto, jak wyglądałby wynik uruchomienia tego SQL:
Sprzężenie zewnętrzne: - Sprzężenie zewnętrzne nie wymaga, aby każdy rekord w dwóch połączonych tabelach miał pasujący rekord. Połączona tabela zachowuje każdy rekord - nawet jeśli nie istnieje inny pasujący rekord. Połączenia zewnętrzne dzielą się dalej na lewe połączenia zewnętrzne i prawe połączenia zewnętrzne, w zależności od tego, które wiersze tabeli zostaną zachowane (lewe czy prawe).
Lewe sprzężenie zewnętrzne : - Wynik lewego sprzężenia zewnętrznego (lub po prostu lewego sprzężenia) dla tabel Pracownik i lokalizacja zawsze zawiera wszystkie rekordy „lewej” tabeli ( Pracownik ), nawet jeśli warunek łączenia nie znajdzie żadnego pasującego rekordu w „prawa” tabela ( lokalizacja ). Oto, jak wyglądałby SQL dla lewego złączenia zewnętrznego, korzystając z powyższych tabel:
select * from employee left outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Oto, jak wyglądałby wynik uruchomienia tego SQL:
Prawy łącznik zewnętrzny: - Prawy łącznik zewnętrzny (lub łącznik prawy) bardzo przypomina lewe łączenie zewnętrzne, z wyjątkiem odwróconego traktowania tabel. Każdy wiersz z „prawej” tabeli ( lokalizacji ) pojawi się w połączonej tabeli przynajmniej raz. Jeśli nieistniejepasujący wiersz z tabeli „po lewej” ( pracownik ), w kolumnach pracownika pojawi się wartość NULLdla tych rekordów, które nie pasują do lokalizacji . Tak wygląda SQL:
select * from employee right outer join location on employee.empID = location.empID;
//Use of outer keyword is optional
Korzystając z powyższych tabel, możemy pokazać, jak wyglądałby zestaw wyników prawego połączenia zewnętrznego:
Pełne połączenia zewnętrzne: - sprzężenia Pełne sprzężenie zewnętrzne lub pełne sprzężenie to zachowanie informacji niepasujących poprzez dołączenie niepasujących wierszy w wynikach sprzężenia, użycie pełnego sprzężenia zewnętrznego. Obejmuje wszystkie wiersze z obu tabel, niezależnie od tego, czy druga tabela ma pasującą wartość.
Pobierz tylko dopasowane wiersze, czyli A intersect B
.
SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Wybierz wszystkie rekordy z pierwszej tabeli i wszelkie rekordy w drugiej tabeli, które pasują do połączonych kluczy.
SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
Wybierz wszystkie rekordy z drugiej tabeli i wszelkie rekordy w pierwszej tabeli, które pasują do połączonych kluczy.
SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
ON S.Advisor_ID = A.Advisor_ID
W prostych słowach:
Sprzężenia wewnętrznego pobiera tylko dopasowane wiersze.
Podczas gdy sprzężenie zewnętrzne pobiera dopasowane wiersze z jednej tabeli i wszystkich wierszy w drugiej tabeli ... wynik zależy od tego, którego używasz:
Po lewej : Dopasowane wiersze w prawej tabeli i wszystkie wiersze w lewej tabeli
Po prawej : Dopasowane wiersze w lewej tabeli i wszystkie wiersze w prawej tabeli lub
Pełny : wszystkie wiersze we wszystkich tabelach. Nie ma znaczenia, czy istnieje dopasowanie, czy nie
Łączenie wewnętrzne pokazuje wiersze tylko wtedy, gdy po drugiej (prawej) stronie złączenia znajduje się pasujący rekord.
(Lewe) sprzężenie zewnętrzne pokazuje wiersze dla każdego rekordu po lewej stronie, nawet jeśli nie ma pasujących wierszy po drugiej (prawej) stronie sprzężenia. Jeśli nie ma pasującego wiersza, kolumny dla drugiej (prawej) strony pokazywałyby NULL.
Połączenia wewnętrzne wymagają, aby rekord z powiązanym identyfikatorem istniał w połączonej tabeli.
Sprzężenia zewnętrzne zwrócą rekordy dla lewej strony, nawet jeśli nic nie istnieje dla prawej strony.
Na przykład masz tabelę Zamówienia i Szczegóły zamówienia. Są one powiązane przez „OrderID”.
Zamówienia
Szczegóły zamówienia
Prośba
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
zwróci tylko Zamówienia, które również mają coś w tabeli OrderDetails.
Jeśli zmienisz to na OUTER LEFT JOIN
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
wtedy zwróci rekordy z tabeli Zamówienia, nawet jeśli nie mają żadnych rekordów OrderDetails.
Możesz użyć tego, aby znaleźć Zamówienia, które nie mają żadnych Szczegółów Zamówienia wskazujących na możliwe osierocone zamówienie, dodając klauzulę where WHERE OrderDetails.OrderID IS NULL
.
SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c, categories_description cd WHERE c.id = cd.categories_id AND c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC
do SELECT c.id, c.status, cd.name, c.parent_id, cd.description, c.image FROM categories c INNER JOIN categories_description cd ON c.id = cd.categories_id WHERE c.status = 1 AND cd.language_id = 2 ORDER BY c.parent_id ASC
(MySQL) z sukcesem. Nie byłem pewien co do dodatkowych warunków, dobrze się mieszają ...
W prostych słowach:
Wewnętrzne dołączenie -> Pobieraj TYLKO wspólne rekordy z tabel nadrzędnych i podrzędnych GDZIE klucz podstawowy tabeli nadrzędnej pasuje do klucza obcego w tabeli podrzędnej.
Lewy dołącz ->
pseudo kod
1.Take All records from left Table
2.for(each record in right table,) {
if(Records from left & right table matching on primary & foreign key){
use their values as it is as result of join at the right side for 2nd table.
} else {
put value NULL values in that particular record as result of join at the right side for 2nd table.
}
}
Prawe dołączenie : dokładnie odwrotnie niż lewe łączenie. Wpisz nazwę tabeli w LEWE DOŁĄCZ po prawej stronie w Prawe połączenie, otrzymasz takie samo wyjście jak LEWE DOŁĄCZ.
Łączenie zewnętrzne : Pokaż wszystkie rekordy w obu tabelachNo matter what
. Jeśli rekordy w lewej tabeli nie są zgodne z prawą tabelą opartą na kluczu podstawowym, Forieign, użyj wartości NULL w wyniku łączenia.
Przykład:
Załóżmy teraz dla 2 tabel
1.employees , 2.phone_numbers_employees
employees : id , name
phone_numbers_employees : id , phone_num , emp_id
Tutaj tabela pracowników jest tabelą główną, numery_elefonów_pracowników to tabela podrzędna (zawiera ona emp_id
jako klucz obcy, który łączy się employee.id
z tabelą podrzędną).
Połączenia wewnętrzne
Zapisy 2 tabel TYLKO JEŚLI Klucz podstawowy tabeli pracowników (jego identyfikator) pasuje do klucza obcego tabeli podrzędnej numery_elefonów_pracowników (emp_id) .
Tak więc zapytanie byłoby:
SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Tutaj weź tylko pasujące wiersze na kluczu podstawowym = klucz obcy, jak wyjaśniono powyżej. Tutaj niepasujące wiersze na kluczu podstawowym = klucz obcy są pomijane w wyniku łączenia.
Lewe dołączenia :
Łączenie z lewej strony zachowuje wszystkie wiersze z lewej tabeli, niezależnie od tego, czy w prawej tabeli znajduje się pasujący wiersz.
SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Połączenia zewnętrzne :
SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
Schematycznie wygląda to tak:
Użyj, INNER JOIN
aby zwrócić wszystkie wiersze z obu tabel, w których występuje dopasowanie. tzn. w wynikowej tabeli wszystkie wiersze i kolumny będą miały wartości.
W OUTER JOIN
wynikowej tabeli mogą znajdować się puste kolumny. Sprzężenie zewnętrzne mogą być LEFT
alboRIGHT
.
LEFT OUTER JOIN
zwraca wszystkie wiersze z pierwszej tabeli, nawet jeśli nie ma żadnych dopasowań w drugiej tabeli.
RIGHT OUTER JOIN
zwraca wszystkie wiersze z drugiej tabeli, nawet jeśli w pierwszej tabeli nie ma żadnych dopasowań.
To jest dobre, schematyczne wyjaśnienie dla wszystkich rodzajów złączeń
źródło: http://ssiddique.info/understanding-sql-joins-in-easy-way.html
INNER JOIN
wymaga co najmniej dopasowania w porównaniu dwóch tabel. Na przykład tabela A i tabela B, która implikuje A ٨ B (przecięcie A).
LEFT OUTER JOIN
i LEFT JOIN
są takie same. Daje wszystkie rekordy pasujące w obu tabelach i wszystkie możliwości lewej tabeli.
Podobnie RIGHT OUTER JOIN
i RIGHT JOIN
są takie same. Daje wszystkie rekordy pasujące do obu tabel i wszystkie możliwości właściwej tabeli.
FULL JOIN
jest kombinacją LEFT OUTER JOIN
iRIGHT OUTER JOIN
powielania bez niego.
Odpowiedź ma znaczenie w każdym z nich, a więc w wynikach.
Uwaga:
WSQLite
nie maRIGHT OUTER JOIN
lubFULL OUTER JOIN
.
A takżeMySQL
nie maFULL OUTER JOIN
.
Moja odpowiedź oparta jest na powyższej uwadze .
Gdy masz dwie takie tabele:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
CROSS JOIN / OUTER JOIN:
Możesz mieć wszystkie dane z tych tabel z CROSS JOIN
lub po prostu w ,
ten sposób:
SELECT * FROM table1, table2
--[OR]
SELECT * FROM table1 CROSS JOIN table2
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
1 | a1 | 3 | b2
2 | b1 | 1 | a2
2 | b1 | 3 | b2
DOŁĄCZ DO WEWNĘTRZNEJ:
Jeśli chcesz dodać filtr do powyższych wyników na podstawie relacji, table1.id = table2.id
której możesz użyć INNER JOIN
:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
--[OR]
SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
DOŁĄCZ DO LEWEGO [ZEWNĘTRZNEGO]:
Jeśli chcesz mieć wszystkie wiersze jednego z tabel w powyższym wyniku - z tą samą relacją - możesz użyć LEFT JOIN
:
(W przypadku PRAWEGO DOŁĄCZU zmień miejsce tabel)
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
--[OR]
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
DOŁĄCZ DO PEŁNEGO ZEWNĘTRZNEGO:
Jeśli chcesz, aby w wynikach były również wszystkie wiersze drugiej tabeli, możesz użyć FULL OUTER JOIN
:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
UNION ALL
SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
--[OR] (recommended for SQLite)
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION ALL
SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
WHERE table1.id IS NULL
--[OR]
SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
--[Results:]
id | name | id | name
-----+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
Null | Null | 3 | b2
Cóż, w zależności od potrzeb wybierasz każdą, która zaspokoi twoją potrzebę;).
full outer join
MySQL też nie ma .
Wewnętrzne dołączenie.
Łączenie polega na łączeniu wierszy z dwóch tabel. Sprzężenia wewnętrznego próbuje dopasować się dwie tabele oparte na kryteriach określonych na zapytania i zwraca tylko wiersze spełniające. Jeśli wiersz z pierwszej tabeli w złączeniu pasuje do dwóch wierszy w drugiej tabeli, wówczas dwa wiersze zostaną zwrócone w wynikach. Jeśli w pierwszej tabeli jest wiersz, który nie pasuje do wiersza w drugiej, nie jest zwracany; podobnie, jeśli w drugiej tabeli jest wiersz, który nie pasuje do wiersza w pierwszym, nie jest zwracany.
Outer Join.
Lewo dołączyć próby znalezienia dopasować wiersze z pierwszej tabeli do wierszy w drugiej tabeli. Jeśli nie może znaleźć dopasowania, zwróci kolumny z pierwszej tabeli i pozostawi kolumny z drugiej tabeli puste (null).
INNER JOIN
najbardziej typowe łączenie dla dwóch lub więcej tabel. Zwraca dopasowanie danych zarówno dla relacji ON keykey, jak i forignkey.OUTER JOIN
jest taki sam jak INNER JOIN
, ale zawiera również NULL
dane w ResultSet.
LEFT JOIN
= INNER JOIN
+ Niedopasowane dane lewej tabeli z Null
dopasowaniem na prawej tabeli.RIGHT JOIN
= INNER JOIN
+ Niedopasowane dane prawej tabeli z Null
dopasowaniem na lewej tabeli.FULL JOIN
= INNER JOIN
+ Niedopasowane dane w obu tabelach po prawej i lewej stronie z Null
dopasowaniami.INNER JOIN
i OUTER JOIN
możemy pisać zapytania do samodzielnego dołączania.Na przykład:
SELECT *
FROM tablea a
INNER JOIN tableb b
ON a.primary_key = b.foreign_key
INNER JOIN tablec c
ON b.primary_key = c.foreign_key
Nie widzę wielu szczegółów na temat wydajności i optymalizatora w innych odpowiedziach.
Czasami dobrze jest wiedzieć tylko to INNER JOIN
jest asocjacyjny, co oznacza, że optymalizator ma najwięcej opcji, aby się nim bawić. Może zmienić kolejność łączenia, aby przyspieszyć utrzymanie tego samego wyniku. Optymalizator może korzystać z większości trybów łączenia.
Zasadniczo dobrą praktyką jest próba użycia INNER JOIN
zamiast innego rodzaju złączeń. (Oczywiście, jeśli jest to możliwe, biorąc pod uwagę oczekiwany zestaw wyników).
Istnieje kilka dobrych przykładów i wyjaśnień na temat tego dziwnego zachowania asocjacyjnego:
INNER JOIN
jest wolniejszy niż LEFT JOIN
w większości przypadków, I ludzie mogą używać LEFT JOIN
zamiast INNER JOIN
dodawać WHERE
do usuwania nieoczekiwanych NULL
wyników;).
INNER
jest wolniejszy?
Po skrytykowaniu uwielbianego na czerwono odcienia diagramu Venna, pomyślałem, że sprawiedliwe jest opublikowanie własnej próby.
Chociaż odpowiedź @Martin Smith jest najlepsza z tej grupy, jego jedyna pokazuje kluczową kolumnę z każdej tabeli, podczas gdy uważam, że idealnie powinny być pokazane również kolumny niekluczowe.
Najlepsze, co mogłem zrobić w dozwolonym półgodzinie, wciąż nie sądzę, aby odpowiednio pokazywało, że wartości zerowe istnieją ze względu na brak kluczowych wartości w środku TableB
lub że w OUTER JOIN
rzeczywistości jest to związek, a nie połączenie:
TableA a LEFT OUTER JOIN TableB b
zTableB B RIGHT OUTER JOIN TableA a
Dokładny algorytm INNER JOIN
, LEFT/RIGHT OUTER JOIN
są następujące:
a
(a, b[i])
ON ...
klauzulę dla każdej pary:ON( a, b[i] ) = true/false?
true
, zwróć ten połączony wiersz (a, b[i])
.Outer Join
następnie para (wirtualna) używająca Null
dla wszystkich kolumn innej tabeli: (a, Null)
dla LEWEGO połączenia zewnętrznego lub (Null, b)
dla PRAWEGO połączenia zewnętrznego. Ma to na celu zapewnienie, że wszystkie wiersze pierwszej tabeli istnieją w końcowych wynikach.Uwaga: warunek określony w ON
klauzuli może być dowolny, nie trzeba używać kluczy podstawowych (i nie zawsze trzeba odwoływać się do kolumn z obu tabel)! Na przykład:
... ON T1.title = T2.title AND T1.version < T2.version
(=> zobacz ten post jako przykładowe użycie: wybierz tylko wiersze o maksymalnej wartości w kolumnie )... ON T1.y IS NULL
... ON 1 = 0
(tak jak próbka)Uwaga: Lewy łączenie = lewy łącznik zewnętrzny, prawy łącznik = prawy łącznik zewnętrzny.
Najprostsze definicje
Łączenie wewnętrzne: Zwraca dopasowane rekordy z obu tabel.
Full Outer Join: Zwraca dopasowane i niedopasowane rekordy z obu tabel z null dla niepasujących rekordów z obu tabel .
Left Outer Join: Zwraca dopasowane i niedopasowane rekordy tylko z tabeli po lewej stronie .
Right Outer Join: Zwraca dopasowane i niedopasowane rekordy tylko z tabeli po prawej stronie .
W skrócie
Dopasowane + lewe niedopasowane + prawe niedopasowane = całkowite połączenie zewnętrzne
Dopasowane + lewy niedopasowany = lewy zewnętrzny łącznik
Dopasowane + prawy niedopasowany = prawy zewnętrzny łącznik
Dopasowane = połączenie wewnętrzne
W prostych słowach,
1. DOŁĄCZ DO WEWNĘTRZNEJ LUB DOŁĄCZONEJ EQUI: Zwraca zestaw wyników, który pasuje tylko do warunku w obu tabelach.
2. DOŁĄCZ DO ZEWNĘTRZNEJ: Zwraca zestaw wyników wszystkich wartości z obu tabel, nawet jeśli warunek jest zgodny lub nie.
3. LEWE DOŁĄCZ: Zwraca zestaw wyników wszystkich wartości z lewej tabeli i tylko wiersze, które pasują do warunków w prawej tabeli.
4. PRAWE DOŁĄCZ: Zwraca zestaw wyników wszystkich wartości z prawej tabeli i tylko wiersze, które pasują do warunków w lewej tabeli.
5. PEŁNE DOŁĄCZENIE: Pełne połączenie i pełne połączenie zewnętrzne są takie same.
Przykłady
Załóżmy, że masz dwie tabele, każda z jedną kolumną i dane w następujący sposób:
A B
- -
1 3
2 4
3 5
4 6
7
8
Zauważ, że (1,2,7,8) są unikalne dla A, (3,4) są wspólne, a (5,6) są unikalne dla B.
Słowo kluczowe INNER JOIN wybiera wszystkie wiersze z obu tabel, o ile warunek jest spełniony. To słowo kluczowe utworzy zestaw wyników, łącząc wszystkie wiersze z obu tabel, w których warunek jest spełniony, tzn. Wartość wspólnego pola będzie taka sama.
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
Wynik:
a | b
--+--
3 | 3
4 | 4
To połączenie zwraca wszystkie wiersze tabeli po lewej stronie złączenia i pasujące wiersze dla tabeli po prawej stronie złączenia. Wiersze, dla których nie ma pasującego wiersza po prawej stronie, zestaw wyników będzie zawierał null. LEFT JOIN jest również znany jako LEFT OUTER JOIN
.
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
Wynik:
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
7 | null
8 | null
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
Wynik:
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
DOŁĄCZ DO PEŁNEJ (ZEWNĘTRZNEJ) :
FULL JOIN tworzy zestaw wyników, łącząc wynik LEWEGO DOŁĄCZENIA i PRAWEGO DOŁĄCZENIA. Zestaw wyników będzie zawierał wszystkie wiersze z obu tabel. Wiersze, dla których nie ma dopasowania, zestaw wyników będzie zawierać wartości NULL.
select * from a FULL OUTER JOIN b on a.a = b.b;
Wynik:
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
7 | null
8 | null
Wewnętrzna dołączyć - W sprzężenia wewnętrznego przy użyciu jednej z równoważnych zapytaniami daje przecięcie dwóch tabel , czyli dwa rzędy mają wspólnego.
Lewe sprzężenie zewnętrzne - lewe sprzężenie zewnętrzne da wszystkie wiersze w A plus wszystkie wspólne wiersze w B.
Pełne połączenie zewnętrzne - Pełne połączenie zewnętrzne da ci połączenie A i B, tzn. Wszystkie wiersze w A i wszystkie wiersze w B. Jeśli coś w A nie ma odpowiadającego układu odniesienia w B, to część B jest null i vice versay
Join is not an intersection unless the tables have the same columns
Nie. Możesz dołączyć dowolne kolumny, a jeśli wartość będzie zgodna, połączą się one ze sobą.
1. Łączenie wewnętrzne: nazywane również łączeniem. Zwraca wiersze obecne zarówno w lewej tabeli, jak i prawej tabeli, tylko jeśli istnieje dopasowanie . W przeciwnym razie zwraca zero rekordów.
Przykład:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
INNER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
2. Full Outer Join: nazywany również Full Join. Zwraca wszystkie wiersze znajdujące się zarówno w lewej tabeli, jak i prawej tabeli.
Przykład:
SELECT
e1.emp_name,
e2.emp_salary
FROM emp1 e1
FULL OUTER JOIN emp2 e2
ON e1.emp_id = e2.emp_id
3. Lewy zewnętrzny łącznik: Lub po prostu wywoływany jako lewy łączący. Zwraca wszystkie wiersze znajdujące się w lewej tabeli i pasujące wiersze z prawej tabeli (jeśli istnieją).
4. Right Outer Join: Zwany także jako Right Join. Zwraca pasujące wiersze z lewej tabeli (jeśli istnieją) i wszystkie wiersze znajdujące się w prawej tabeli.
Zalety połączeń
Rozważ poniżej 2 tabele:
EMP
empid name dept_id salary
1 Rob 1 100
2 Mark 1 300
3 John 2 100
4 Mary 2 300
5 Bill 3 700
6 Jose 6 400
Departament
deptid name
1 IT
2 Accounts
3 Security
4 HR
5 R&D
Najczęściej napisane jako DOŁĄCZ w zapytaniach SQL. Zwraca tylko pasujące rekordy między tabelami.
Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
Jak widać powyżej, Jose
nie jest drukowane z EMP w danych wyjściowych, ponieważ dept_id 6
nie znajduje dopasowania w tabeli działu. Podobnie, HR
a R&D
wiersze nie są drukowane z Departamentu tabeli, ponieważ nie znaleźliśmy mecz w tabeli EMP.
Zatem INNER JOIN lub po prostu JOIN, zwraca tylko pasujące wiersze.
Zwraca wszystkie rekordy z tabeli LEWEJ i tylko pasujące rekordy z tabeli PRAWEJ.
Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
6 Jose
Tak więc, jeśli zaobserwujesz powyższy wynik, wszystkie rekordy z tabeli LEFT (Emp) zostaną wydrukowane z pasującymi rekordami z tabeli RIGHT.
HR
i R&D
wiersze nie są drukowane z tabeli Departamentu, ponieważ nie znalazły dopasowania w tabeli Emp na dept_id.
Zatem LEFT JOIN zwraca WSZYSTKIE wiersze z lewej tabeli i tylko pasujące wiersze z prawej tabeli.
Możesz również sprawdzić DEMO tutaj .
Proszę zobaczyć odpowiedź przez Martina Smitha przez lepszych illustations i objaśnienie różnych łączy, a zwłaszcza w tym różnice między FULL OUTER JOIN
, RIGHT OUTER JOIN
i LEFT OUTER JOIN
.
Te dwie tabele stanowią podstawę do przedstawienia JOIN
poniższych s:
SELECT *
FROM citizen
CROSS JOIN postalcode
Rezultatem będą produkty kartezjańskie wszystkich kombinacji. Nie JOIN
wymaga warunek:
INNER JOIN
jest taki sam jak po prostu: JOIN
SELECT *
FROM citizen c
JOIN postalcode p ON c.postal = p.postal
Rezultatem będą kombinacje, które spełniają wymagany JOIN
warunek:
LEFT OUTER JOIN
jest taki sam jak LEFT JOIN
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
Rezultatem będzie wszystko, citizen
nawet jeśli nie będzie żadnych dopasowań postalcode
. Ponownie JOIN
wymagany jest warunek:
Wszystkie przykłady zostały uruchomione na Oracle 18c. Są one dostępne na stronie dbfiddle.uk, skąd pochodzą również zrzuty ekranów tabel.
CREATE TABLE citizen (id NUMBER,
name VARCHAR2(20),
postal NUMBER, -- <-- could do with a redesign to postalcode.id instead.
leader NUMBER);
CREATE TABLE postalcode (id NUMBER,
postal NUMBER,
city VARCHAR2(20),
area VARCHAR2(20));
INSERT INTO citizen (id, name, postal, leader)
SELECT 1, 'Smith', 2200, null FROM DUAL
UNION SELECT 2, 'Green', 31006, 1 FROM DUAL
UNION SELECT 3, 'Jensen', 623, 1 FROM DUAL;
INSERT INTO postalcode (id, postal, city, area)
SELECT 1, 2200, 'BigCity', 'Geancy' FROM DUAL
UNION SELECT 2, 31006, 'SmallTown', 'Snizkim' FROM DUAL
UNION SELECT 3, 31006, 'Settlement', 'Moon' FROM DUAL -- <-- Uuh-uhh.
UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space' FROM DUAL;
JOIN
iWHERE
CROSS JOIN
w wyniku czego powstały wiersze jako Ogólna idea / INNER JOIN
:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows
Użycie CROSS JOIN
do uzyskania wyniku LEFT OUTER JOIN
wymaga sztuczek, takich jak dodawanie z NULL
rzędu. Zostało pominięte
INNER JOIN
staje się produktami kartezjańskimi. To to samo, co Ogólny pomysł / CROSS JOIN
:
SELECT *
FROM citizen c
JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
W tym miejscu połączenie wewnętrzne można naprawdę postrzegać jako połączenie krzyżowe z usuniętymi wynikami niezgodnymi z warunkiem. Tutaj żaden z wynikowych wierszy nie jest usuwany.
Użycie INNER JOIN
do uzyskania wyniku LEFT OUTER JOIN
również wymaga sztuczek. Zostało pominięte
LEFT JOIN
wyniki w wierszach jako Ogólna idea / CROSS JOIN
:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
LEFT JOIN
wyniki w wierszach jako Ogólna idea / INNER JOIN
:
SELECT *
FROM citizen c
LEFT JOIN postalcode p ON c.postal = p.postal
WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode
Internetowe wyszukiwanie obrazów w „sql join cross internal outer” pokaże wiele diagramów Venna. Kiedyś miałem na biurku wydrukowaną kopię. Ale są problemy z reprezentacją.
Schemat Venna doskonale nadaje się do teorii zbiorów, w której element może znajdować się w jednym lub obu zestawach. Ale w przypadku baz danych element w jednym „zestawie” wydaje mi się być wierszem w tabeli, a zatem nie występuje w żadnej innej tabeli. Nie ma czegoś takiego jak jeden wiersz obecny w wielu tabelach. Wiersz jest unikalny dla tabeli.
Połączenia automatyczne to przypadek narożny, w którym każdy element jest w rzeczywistości taki sam w obu zestawach. Ale nadal nie jest wolny od żadnego z poniższych problemów.
Zestaw A
reprezentuje zestaw po lewej stronie ( citizen
tabela), a zestaw B
jest zestawem po prawej stronie ( postalcode
tabela) w poniższej dyskusji.
Każdy element w obu zestawach jest dopasowany do każdego elementu w drugim zestawie, co oznacza, że potrzebujemy A
ilości każdego B
elementu i B
ilości każdego A
elementu, aby poprawnie reprezentować ten kartezjański produkt. Teoria zbiorów nie jest stworzona dla wielu identycznych elementów w zestawie, więc uważam, że diagramy Venna właściwie przedstawiają to jako niepraktyczne / niemożliwe. Wygląda na to, że UNION
w ogóle nie pasuje.
Rzędy są różne. UNION
Jest 7 rzędów w całości. Ale są niekompatybilne dla wspólnego SQL
zestawu wyników. I wcale tak nie CROSS JOIN
działa:
Próbuję to przedstawić w następujący sposób:
.. ale teraz wygląda to jak coś INTERSECTION
, co z pewnością nie jest . Co więcej, nie ma w nim żadnego elementu, INTERSECTION
który byłby w żadnym z dwóch odrębnych zestawów. Wygląda jednak bardzo podobnie do wyników wyszukiwania podobnych do tego:
Dla porównania, jeden wynik wyszukiwania dla CROSS JOIN
s można zobaczyć na Tutorialgateway . Tak INTERSECTION
jak ten, jest pusty.
Wartość elementu zależy od JOIN
warunku. Można to przedstawić pod warunkiem, że każdy wiersz stanie się unikalny dla tego warunku. Znaczenie id=x
jest prawdziwe tylko dla jednego wiersza. Gdy wiersz w table A
( citizen
) pasuje do wielu wierszy w table B
( postalcode
) pod JOIN
warunkiem, wynik ma takie same problemy jak CROSS JOIN
: Wiersz musi być reprezentowany wiele razy, a teoria mnogości nie jest do tego stworzona. Pod warunkiem wyjątkowości diagram może jednak działać, ale należy pamiętać, że JOIN
warunek określa umiejscowienie elementu na diagramie. Patrząc tylko na wartości JOIN
warunku wraz z resztą rzędu tuż przed jazdą:
Reprezentacja ta znajduje się całkowicie od siebie przy używaniu INNER JOIN
w ON 1 = 1
stanie ją sporządza się na klasę CROSS JOIN
.
W przypadku self- JOIN
wiersze są w rzeczywistości identycznymi elementami w obu tabelach, ale reprezentują tabele jako oba A
i B
nie są zbyt odpowiednie. Na przykład powszechnym JOIN
warunkiem własnym , który sprawia, że element A
jest dopasowywany do innego elementu w B, jest ON A.parent = B.child
dopasowanie od A
do B
na osobnych elementach. Z przykładów, które wyglądałyby SQL
tak:
SELECT *
FROM citizen c1
JOIN citizen c2 ON c1.id = c2.leader
Znaczenie Smith jest liderem zarówno Green, jak i Jensen.
Ponownie problemy zaczynają się, gdy jeden wiersz ma wiele dopasowań do wierszy w drugiej tabeli. Jest to dodatkowo skomplikowane, ponieważ OUTER JOIN
można dopasować pusty zestaw. Ale w teorii zbiorów połączenie dowolnego zbioru C
i pustego zbioru jest zawsze sprawiedliwe C
. Pusty zestaw nic nie dodaje. Reprezentacja tego LEFT OUTER JOIN
zwykle pokazuje po prostu wszystko, A
aby zilustrować, że wiersze w A
są wybierane niezależnie od tego, czy istnieje dopasowanie, czy nie B
. „Dopasowane elementy” mają jednak takie same problemy jak na powyższej ilustracji. Zależą od stanu. I wydaje się, że pusty zestaw wędrował do A
:
Znajdowanie wszystkich wierszy za CROSS JOIN
pomocą Smitha i kodu pocztowego na Księżycu:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
AND p.area = 'Moon';
Teraz diagram Venna nie jest używany do odzwierciedlenia JOIN
. Jest używany tylko w przypadku WHERE
klauzuli:
... i to ma sens.
Jak wyjaśniono, INNER JOIN
tak naprawdę nie jest INTERSECT
. Jednak INTERSECT
mogą być stosowane s na wynikach oddzielne zapytaniami. Tutaj diagram Venna ma sens, ponieważ elementy z oddzielnych zapytań są w rzeczywistości wierszami, które albo należą do jednego z wyników, albo do obu. Przecięcie oczywiście zwróci wyniki tylko wtedy, gdy wiersz jest obecny w obu zapytaniach. Spowoduje SQL
to powstanie tego samego wiersza, co powyższy WHERE
, a diagram Venna będzie również taki sam:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
INTERSECT
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
An OUTER JOIN
nie jest UNION
. Pracuj jednak UNION
w tych samych warunkach co INTERSECT
, co powoduje zwrócenie wszystkich wyników łączących oba SELECT
s:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
UNION
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE p.area = 'Moon';
co jest równoważne z:
SELECT *
FROM citizen c
CROSS JOIN postalcode p
WHERE c.name = 'Smith'
OR p.area = 'Moon';
.. i daje wynik:
Również tutaj schemat Venna ma sens:
Ważną uwagą jest to, że działają one tylko wtedy, gdy struktura wyników z dwóch SELECT jest taka sama, umożliwiając porównanie lub połączenie. Wyniki tych dwóch nie umożliwią:
SELECT *
FROM citizen
WHERE name = 'Smith'
SELECT *
FROM postalcode
WHERE area = 'Moon';
... próba połączenia wyników UNION
daje
ORA-01790: expression must have same datatype as corresponding expression
W celu dalszego zainteresowania przeczytaj powiedz NIE diagramom Venna podczas wyjaśniania JOIN i złączeń sql jako diagram Venna . Oba obejmują również EXCEPT
.
Jest tu wiele dobrych odpowiedzi z bardzo dokładnymi przykładowymi relacjami z algebry . Oto bardzo uproszczona odpowiedź, która może być pomocna dla amatorów lub początkujących programistów z dylematami kodowania SQL.
Zasadniczo częściej zapytania JOIN
sprowadzają się do dwóch przypadków:
W przypadku SELECT
podzbioru danych A
:
INNER JOIN
gdy powiązane dane B
, których szukasz, MUSZĄ istnieć według projektu bazy danych;LEFT JOIN
gdy powiązane dane B
, których szukasz, MOCĄ lub MOCĄ NIE istnieją zgodnie z projektem bazy danych.Różnica między inner join
i outer join
jest następująca:
Inner join
jest złączeniem, które łączy tabele oparte na dopasowujących krotkach, podczas gdy outer join
jest złączeniem, które łączy tabele oparte na dopasowanej i niepasującej krotce.Inner join
scala dopasowany wiersz z dwóch tabel, w którym pomijany jest niedopasowany wiersz, natomiast outer join
scala wiersze z dwóch tabel i niepasujące wiersze wypełniają się wartością null.Inner join
jest jak operacja przecięcia, podczas gdy outer join
jest jak operacja związkowa.Inner join
to dwa typy, podczas gdy outer join
są trzy typy.outer join
jest szybszy niż inner join
.