Jaka jest różnica między „INNER JOIN” a „OUTER JOIN”?


4670

Także jak zrobić LEFT JOIN, RIGHT JOINi FULL JOINzmieścić się w?


63
Spośród odpowiedzi i komentarzy oraz odnośników poniżej tylko jeden faktycznie wyjaśnia, w jaki sposób diagramy Venna przedstawiają operatory: Obszar przecięcia okręgu reprezentuje zestaw wierszy w JOIN B. Obszar unikalny dla każdego okręgu reprezentuje zestaw wierszy, które otrzymujesz, biorąc jego wiersze tabeli, które nie uczestniczą w A JOIN B i dodając kolumny unikalne do drugiej tabeli, wszystkie ustawione na NULL. (I większość podaje niejasną fałszywą korespondencję kręgów do A i B.)
philipxy

1
Przeskakując od odpowiedzi opartych na teorii poniżej, do aplikacji w świecie rzeczywistym: często pracuję z danymi eksperymentów, testując wzorce procesorów. Często chcę porównać wyniki między 2 lub więcej opcjami sprzętowymi. INNER JOIN oznacza, że ​​widzę tylko testy porównawcze, które przebiegły pomyślnie we wszystkich eksperymentach; OUTER JOIN oznacza, że ​​mogę zobaczyć wszystkie eksperymenty, w tym te, które nie działały w niektórych konfiguracjach. Ważne jest, aby widzieć niepowodzenia w takich eksperymentach, a także sukcesy. Na tyle ważne, że napisałem PerlSQL, aby uzyskać ZEWNĘTRZNE DOŁĄCZENIE, gdy wielu RDBMS go brakowało
Krazy Glew

4
Podano już wiele odpowiedzi, ale nie widziałem tego samouczka. Jeśli znasz diagramy Venna, jest to WIELKI samouczek: blog.codinghorror.com/a-visual-explanation-of-sql-joins Dla mnie jest to wystarczająco zwięzłe, aby być szybkim lekturą, ale wciąż chwyta całą koncepcję i działa wszystkie przypadki bardzo dobrze. Jeśli nie wiesz, czym są diagramy Venna - naucz się ich. Zajmuje to 5–10 minut i pomoże, gdy zajdzie potrzeba wizualizacji pracy z zestawami i zarządzania operacjami na zestawach.
DanteTheSmith

14
@DanteTheSmith Nie, który ma te same problemy, co schematy tutaj. Zobacz mój komentarz powyżej, pytanie i poniżej ten post na blogu: „Jeff odrzuca swojego bloga kilka stron w komentarzach”. Diagramy Venna pokazują elementy w zestawach. Po prostu spróbuj dokładnie określić, jakie są zestawy i jakie elementy są na tych schematach. Zestawy nie są tabelami, a elementy nie są ich rzędami. Można także łączyć dowolne dwie tabele, więc PK i FK są nieistotne. Wszystko fałszywe. Robisz to, co zrobiły tysiące innych - masz niejasne wrażenie, które (błędnie) zakładasz, że ma to sens.
philipxy

3
Chris Polecam przeczytać ten artykuł: towardsdatascience.com/ ... ... i rozważyć zmianę wyboru zaakceptowanej odpowiedzi (być może na tę z nagrodą) na odpowiedź, która nie korzysta ze schematów Venna. Obecnie przyjęta odpowiedź wprowadza w błąd zbyt wiele osób. Zachęcam do zrobienia tego dla dobra naszej społeczności i dla jakości naszej bazy wiedzy.
Colm Bhandal

Odpowiedzi:


6111

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

41
Dobrze byłoby rozszerzyć przykład, dodając kolejny wiersz w tabeli B o wartości 4. To pokaże, że sprzężenia wewnętrzne nie muszą być równe liczbie wierszy.
softveda

472
Doskonałe wyjaśnienie, jednak to stwierdzenie: Zewnętrzne połączenie A i B daje wyniki połączenia A, tj. Zewnętrzne części połączenia diagramu Venna. nie jest dokładnie sformułowany. Połączenie zewnętrzne da wyniki A przecina B oprócz jednego z poniższych: wszystkie A (lewe połączenie), wszystkie B (prawe połączenie) lub wszystkie A i wszystkie B (pełne połączenie). Tylko ten ostatni scenariusz jest tak naprawdę związkiem B. Mimo to dobrze napisane wyjaśnienie.
Thomas

11
Czy mam rację, że FULL JOIN to alias FULL OUTER JOIN, a LEFT JOIN to alias LEFT OUTER JOIN?
Damian

3
tak, świetne i doskonałe wyjaśnienie. ale dlaczego w kolumnie b wartości nie są uporządkowane? czyli 6,5, a nie 5,6?
Ameer

7
@ Odpowiedź, dziękuję. Dołącz nie gwarantuje zamówienia, należy dodać klauzulę ORDER BY.
Mark Harrison

731

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.

  1. Wyobraź sobie połączenie krzyżowe.
  2. Oceń onklauzulę względem wszystkich wierszy z kroku 1, zachowując te, do których predykat oceniatrue
  3. (Tylko dla połączeń zewnętrznych) dodaj z powrotem w zewnętrznych wierszach, które zostały utracone w kroku 2.

(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.

wprowadź opis zdjęcia tutaj


Wyjaśnienie

Tabele źródłowe

wprowadź opis linku tutaj

Najpierw zacznij od CROSS JOIN(produktu kartezjańskiego AKA). To nie ma ONklauzuli i po prostu zwraca każdą kombinację wierszy z dwóch tabel.

WYBIERZ A.KOLOR, B.KOLOR Z KRZYŻA DOŁĄCZ B

wprowadź opis linku tutaj

Złączenia wewnętrzne i zewnętrzne mają predykat „ON”.

  • Przyłączenie wewnętrzne. Oceń warunek w klauzuli „ON” dla wszystkich wierszy wyniku połączenia krzyżowego. Jeśli true, zwróć połączony wiersz. W przeciwnym razie wyrzuć to.
  • Lewy zewnętrzny łącznik. To samo, co połączenie wewnętrzne, a następnie dla wszystkich wierszy w lewej tabeli, które nie pasują do niczego, co wypisuje je z wartościami NULL dla prawej kolumny tabeli.
  • Right Outer Join. To samo co łączenie wewnętrzne, a następnie dla wszystkich wierszy w prawej tabeli, które nie pasują do niczego, co wypisuje je z wartościami NULL dla lewej kolumny tabeli.
  • Pełne połączenie zewnętrzne. Tak samo jak połączenie wewnętrzne, zachowaj lewe niepasujące rzędy, jak w lewym złączu zewnętrznym i prawe niepasujące rzędy, jak w prawym złączu zewnętrznym.

Kilka przykładów

WYBIERZ A.KOLOR, B.KOLOR OD WEWNĘTRZNEGO DOŁĄCZENIA B NA A.KOLOR = B.KOLOR

Powyżej jest klasyczne połączenie equi.

Przyłączenie wewnętrzne

Wersja animowana

wprowadź opis zdjęcia tutaj

WYBIERZ A.KOLOR, B.KOLOR OD WEWNĘTRZNEGO DOŁĄCZENIA B NA A.KOLOR NIE WŁĄCZONY („zielony”, „niebieski”)

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ść.

wewnętrzna 2

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.

WYBIERZ A.KOLOR, B.KOLOR Z LEWEGO ZEWNĘTRZNEGO DOŁĄCZ DO B NA A.KOLOR = B.KOLOR

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 NULLwartościami dla kolumny po prawej stronie.

LOJ

WYBIERZ A.KOLOR, B.KOLOR OD LEWEGO DOŁĄCZENIA ZEWNĘTRZNEGO B NA A.KOLOR = B.KOLOR GDZIE B.KOLOR JEST NULL

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 NULLtestu kolumnę, która albo nie ma wartości zerowej, albo dla której warunek łączenia gwarantuje, że wszelkie NULLwartości zostaną wykluczone, aby ten wzorzec działał poprawnie i unikał po prostu przywracania wierszy, które mają taką NULLwartość kolumna oprócz niepasujących wierszy.

Loj ma wartość zerową

WYBIERZ A.KOLOR, B.KOLOR OD PRAWEJ ZEWNĘTRZNEJ DOŁĄCZ DO B NA A.KOLOR = B.KOLOR

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.

ROJ

WYBIERZ A.KOLOR, B.KOLOR Z PEŁNEGO ZEWNĘTRZNEGO DOŁĄCZ DO B NA A.KOLOR = B.KOLOR

Pełne sprzężenia zewnętrzne łączą zachowanie złączeń lewego i prawego i zachowują niepasujące wiersze z lewej i prawej tabeli.

FOJ

WYBIERZ A.KOLOR, B.KOLOR Z PEŁNEJ ZEWNĘTRZNEJ DOŁĄCZ DO B = 1

Żadne wiersze w łączeniu krzyżowym nie pasują do 1=0predykatu. 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.

FOJ 2

WYBIERZ SPÓJNOŚĆ (A.KOLOR, B.KOLOR) JAKO KOLOR Z PEŁNEJ ZEWNĘTRZNEJ DOŁĄCZ DO B = 1 = 0

Po niewielkiej zmianie poprzedniego zapytania można symulować jedną UNION ALLz dwóch tabel.

UNION ALL

WYBIERZ A.KOLOR, B.KOLOR Z LEWEGO DOŁĄCZENIA ZEWNĘTRZNEGO B NA A.KOLOR = B.KOLOR GDZIE B.KOLOR = „ZIELONY”

Zauważ, że WHEREklauzula (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 ...

LOJ

... 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.

LOJtoInner

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

WYBIERZ A.KOLOR, B.KOLOR Z LEWEGO DOŁĄCZENIA ZEWNĘTRZNEGO B NA A.KOLOR = B.KOLOR ORAZ B.KOLOR = „Zielony”

wprowadź opis zdjęcia tutaj

SQL Fiddle

Zobacz te przykłady uruchomione na żywo w SQLFiddle.com .


46
Powiem, że chociaż nie działa to dla mnie tak dobrze jak diagramy Venna, doceniam to, że ludzie różnią się i uczą inaczej i jest to bardzo dobrze przedstawione wyjaśnienie, w przeciwieństwie do wszystkich, które widziałem wcześniej, dlatego wspieram @ypercube w przyznawanie punktów bonusowych. Dobra robota wyjaśniająca różnicę w umieszczaniu dodatkowych warunków w klauzuli JOIN a klauzuli WHERE. Uznanie dla ciebie, Martin Smith.
Old Pro

22
@OldPro Diagramy Venna są OK, jeśli chodzi o ich przebieg, ale chyba nie mówią, jak reprezentować łączenie krzyżowe lub rozróżniać jeden rodzaj predykatu łączenia, taki jak łączenie equi od drugiego. Model mentalny oceny predykatu łączenia w każdym rzędzie wyniku łączenia krzyżowego, a następnie dodawanie z powrotem w niedopasowanych wierszach, jeśli połączenie zewnętrzne, i wreszcie ocena, gdzie działa lepiej dla mnie.
Martin Smith

18
Diagramy Venna są dobre do reprezentowania związków i skrzyżowań i różnic, ale nie łączą się. Mają niewielką wartość edukacyjną w przypadku bardzo prostych połączeń, tj. Połączeń, w których warunki łączenia występują w unikatowych kolumnach.
ypercubeᵀᴹ

12
@Arth - Nie, mylisz się. SQL Fiddle sqlfiddle.com/#!3/9eecb7db59d16c80417c72d1/5155 jest to coś, czego diagramy Venna nie mogą zilustrować.
Martin Smith

7
@MartinSmith Wow, zgadzam się, całkowicie się mylę! Zbyt przyzwyczajony do pracy z jednym do wielu. Dzięki za korektę.
Arth

187

Łą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:

wprowadź opis zdjęcia tutaj

Łą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: wprowadź opis zdjęcia tutaj

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: wprowadź opis zdjęcia tutaj

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:

wprowadź opis zdjęcia tutaj

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ść.

Źródło obrazu

Podręcznik MySQL 8.0 - Dołącz do składni

Oracle Dołącz do operacji


3
najlepsza jak dotąd odpowiedź, alternatywna składnia - tego właśnie szukałem, dzięki!
Joey,

1
Diagramy Venna są błędnie oznaczone. Zobacz moje komentarze do pytania i inne odpowiedzi. Również większość tego języka jest słaba. Np .: „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”. Nie, nie „Gdy predykat łączenia jest spełniony przez dopasowanie wartości innych niż NULL”. Wartości w wierszach nie mają znaczenia poza tym, czy warunek jako całość jest prawdziwy, czy fałszywy. Niektóre wartości mogą być NULL dla prawdziwych warunków.
philipxy

Chociaż nie zostało to wyraźnie stwierdzone, diagramy w tym są diagramami Venna. Diagramy Venna nie są ogólnie poprawną matematyczną charakterystyką złączenia. Sugeruję usunięcie diagramów Venna.
Colm Bhandal

@ ColmBhandal: usunięto diagramy Venna
ajitksharma

Do tekstu używaj tekstu, a nie obrazów / linków - w tym tabel i ERD . Używaj obrazów tylko do tego, co nie może być wyrażone jako tekst lub do rozszerzenia tekstu. Zdjęć nie można wyszukiwać ani wycinać i wklejać. Dołącz legendę / klucz i objaśnienie do obrazu.
philipxy

132

Przyłączenie wewnętrzne

Pobierz tylko dopasowane wiersze, czyli A intersect B.

Wpisz opis zdjęcia tutaj

SELECT *
FROM dbo.Students S
INNER JOIN dbo.Advisors A
    ON S.Advisor_ID = A.Advisor_ID

Lewy zewnętrzny łącznik

Wybierz wszystkie rekordy z pierwszej tabeli i wszelkie rekordy w drugiej tabeli, które pasują do połączonych kluczy.

Wpisz opis zdjęcia tutaj

SELECT *
FROM dbo.Students S
LEFT JOIN dbo.Advisors A
    ON S.Advisor_ID = A.Advisor_ID

Pełne połączenie zewnętrzne

Wybierz wszystkie rekordy z drugiej tabeli i wszelkie rekordy w pierwszej tabeli, które pasują do połączonych kluczy.

Wpisz opis zdjęcia tutaj

SELECT *
FROM dbo.Students S
FULL JOIN dbo.Advisors A
    ON S.Advisor_ID = A.Advisor_ID

Bibliografia


14
Jak nazywa się narzędzie? Uważam, że jest to interesujące, ponieważ pokazuje liczbę wierszy i diagramów Venna
Grijesh Chauhan

2
@GrijeshChauhan Tak Ale możesz spróbować uruchomić go za pomocą wina .
Tushar Gupta - curioustushar

2
Och! tak ... użyłem SQLyoga używając wina .. jest też PlayOnLinux
Grijesh Chauhan

1
Twój tekst jest niejasny i niepoprawny. „Tylko dopasowane wiersze” to rzędy z połączenia krzyżowego A i B, a to, co jest pobierane (połączenie wewnętrzne B), nie jest przecięciem A, ale (połączenie lewe B) przecięcie (połączenie prawe B). „Wybranych” rzędy nie są z A i B, są z poprzecznym przyłączenia B-null rozszerzona wartości wierszy od A i B.
philipxy

@ TusharGupta-curioustushar należy dołączyć „Tabele używane w przykładach SQL”
Manuel Jordan,

111

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


1
@nomen Nie to, że odpowiedź na to pytanie, ale WEJŚCIE WEWNĘTRZNE jest skrzyżowaniem, a PEŁNE DOŁĄCZENIE ZEWNĘTRZNE jest odpowiednią ZJEDNOCZENIE, jeśli lewe i prawe zestawy / okręgi zawierają rzędy (odpowiednio) sprzężenia LEWEGO i PRAWEGO. PS Ta odpowiedź jest niejasna co do wierszy na wejściu i wyjściu. Mylą „w lewej / prawej tabeli” z „ma lewą / prawą część w lewej / prawej” i używa „dopasowanego wiersza” vs.
philipxy

103

Łą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.


81

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

  • OrderID
  • CustomerName

Szczegóły zamówienia

  • OrderDetailID
  • OrderID
  • Nazwa produktu
  • Ilość
  • Cena £

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.


1
Doceniam prosty, ale realistyczny przykład. Zmieniłem żądania jak 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 ASCdo 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ą ...
PhiLho,

68

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:

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_idjako klucz obcy, który łączy się employee.idz 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:

Diagram


4
Wynik nie ma (do zrobienia) nic z kluczami głównymi / unikalnymi / kandydującymi i kluczami obcymi. Bohater może i powinien być opisany bez odniesienia do nich. Obliczane jest połączenie krzyżowe, a następnie wiersze niepasujące do warunku WŁ. Są odfiltrowywane; dodatkowo dla połączeń zewnętrznych rzędy przefiltrowane / niedopasowane rzędy są przedłużane o NULL (na LEWO / PRAWO /
PEŁNIE

Założenie, że sprzężenia SQL zawsze pasują do kluczy głównych / obcych, prowadzi do tego niewłaściwego użycia diagramów Venna. Popraw odpowiednio swoją odpowiedź.
Colm Bhandal

58

Użyj, INNER JOINaby 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 JOINwynikowej tabeli mogą znajdować się puste kolumny. Sprzężenie zewnętrzne mogą być LEFTalboRIGHT .

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ń.



54

INNER JOINwymaga 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 JOINi RIGHT JOINsą takie same. Daje wszystkie rekordy pasujące do obu tabel i wszystkie możliwości właściwej tabeli.

FULL JOINjest kombinacją LEFT OUTER JOINiRIGHT OUTER JOIN powielania bez niego.


43

Odpowiedź ma znaczenie w każdym z nich, a więc w wynikach.

Uwaga:
W SQLitenie ma RIGHT OUTER JOINlub FULL OUTER JOIN.
A także MySQLnie ma FULL 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 JOINlub 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.idktó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ę;).


Możesz dodać do swojej notatki, że full outer joinMySQL też nie ma .
potashin

35

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).


28

wprowadź opis zdjęcia tutaj

  • INNER JOINnajbardziej typowe łączenie dla dwóch lub więcej tabel. Zwraca dopasowanie danych zarówno dla relacji ON keykey, jak i forignkey.
  • OUTER JOINjest taki sam jak INNER JOIN, ale zawiera również NULLdane w ResultSet.
    • LEFT JOIN= INNER JOIN+ Niedopasowane dane lewej tabeli z Nulldopasowaniem na prawej tabeli.
    • RIGHT JOIN= INNER JOIN+ Niedopasowane dane prawej tabeli z Nulldopasowaniem na lewej tabeli.
    • FULL JOIN= INNER JOIN+ Niedopasowane dane w obu tabelach po prawej i lewej stronie z Nulldopasowaniami.
  • Samozłączenie nie jest słowem kluczowym w SQL, gdy tabela sama w sobie odwołuje się do danych, które znają jako samozłączenie. Za pomocą INNER JOINi OUTER JOINmoż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 

27

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 JOINzamiast 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:


4
Używanie jednego rodzaju łączenia nad innym nie może być „dobrą praktyką”. Połączenie, którego używasz, określa dane, które chcesz. Jeśli użyjesz innego, jesteś w błędzie. Dodatkowo w Oracle przynajmniej ta odpowiedź jest całkowicie błędna. Brzmi zupełnie źle dla wszystkiego i nie masz dowodu. Czy masz dowód?
Ben

1. Mam na myśli spróbować użyć. Widziałem wiele osób korzystających z dołączeń LEFT OUTER wszędzie bez żadnego uzasadnionego powodu. (Połączone kolumny nie miały wartości „null”). W takich przypadkach zdecydowanie lepiej byłoby użyć połączeń INNER. 2. Dodałem link lepiej wyjaśniający zachowanie niezwiązane z kojarzeniem.
Lajos Veres

Jak wiem INNER JOINjest wolniejszy niż LEFT JOINw większości przypadków, I ludzie mogą używać LEFT JOINzamiast INNER JOINdodawać WHEREdo usuwania nieoczekiwanych NULLwyników;).
shA.t

Te komentarze sprawiły, że byłem trochę niepewny. Jak myślisz, dlaczego INNERjest wolniejszy?
Lajos Veres

Zależy od silnika. gnu dołącz, joinkeys, DB2, MySQL. Mnóstwo pułapek wydajności, takich jak luźne pisanie lub wyraźna obsada.
mckenzm,

26

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 TableBlub że w OUTER JOINrzeczywistości jest to związek, a nie połączenie:

wprowadź opis zdjęcia tutaj


2
Pytanie dotyczy jednak różnicy między łączeniami WEWNĘTRZNYMI i ZEWNĘTRZNYMI, niekoniecznie pozostawił zewnętrzny
łącznik

@LearnByReading: mój obraz po prawej stronie jest prawo sprzężenia zewnętrznego IE zastąpić TableA a LEFT OUTER JOIN TableB bzTableB B RIGHT OUTER JOIN TableA a
onedaywhen

26

Dokładny algorytm INNER JOIN, LEFT/RIGHT OUTER JOINsą następujące:

  1. Weź każdy wiersz z pierwszego stołu: a
  2. Rozważ wszystkie wiersze z drugiej tabeli obok: (a, b[i])
  3. Oceń ON ...klauzulę dla każdej pary:ON( a, b[i] ) = true/false?
    • Gdy warunek zostanie oceniony jako true, zwróć ten połączony wiersz (a, b[i]) .
    • Po osiągnięciu końca drugiej tabeli bez dopasowania, a jest to Outer Joinnastępnie para (wirtualna) używająca Nulldla 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 ONklauzuli 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:

Łączenie wewnętrzne vs. lewe łączenie zewnętrzne


wprowadź opis zdjęcia tutaj

Uwaga: Lewy łączenie = lewy łącznik zewnętrzny, prawy łącznik = prawy łącznik zewnętrzny.


20

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


1
Jest to genialne i wyjaśnia, dlaczego złączenie nie działa zgodnie z oczekiwaniami dla indeksów Time Series. Znaczniki czasu w odstępie jednej sekundy nie mają sobie równych.
yeliabsalohcin

1
@yeliabsalohcin Nie wyjaśniasz tutaj „zgodnie z oczekiwaniami” ani „działa” w komentarzu do pytania. To tylko jakieś niewyjaśnione osobiste nieporozumienie, którego dziwnie oczekujesz od innych. Jeśli podczas czytania traktujesz słowa tak niechlujnie - źle interpretując jasne pisanie i / lub akceptując niejasne pisanie - jak podczas pisania tutaj, możesz spodziewać się nieporozumień. W rzeczywistości ta odpowiedź, jak większość tutaj, jest niejasna i błędna. „Łączenie wewnętrzne: zwraca dopasowane rekordy z obu tabel” jest niepoprawne, gdy zestawy kolumn wejściowych różnią się. To próbuje powiedzieć coś pewnego, ale to nie jest . (Zobacz moją odpowiedź).
philipxy

9

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.


5

Istnieją dwa główne typy JOIN w SQL: [INNER i OUTER]


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.



  • (WEWNĘTRZNY) DOŁĄCZ :

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.

DOŁĄCZ DO WEWNĘTRZNEGO

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


  • DOŁĄCZ DO LEWEGO (ZEWNĘTRZNEGO) :

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.

LEFT JOIN / 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


  • DOŁĄCZ DO PRAWEJ (ZEWNĘTRZNEJ) : Zwraca wszystkie rekordy z prawej tabeli, a dopasowane rekordy z lewej tabeli

PRAWA DOŁĄCZ / PRAWA DOŁĄCZ DO ZEWNĘTRZNEGO

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.

FULL JOIN / FULL OUTER JOIN

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

1
Diagramy Venna nie wystarczają do opisania złączeń SQL w ogólnym przypadku. Złączenia SQL niekoniecznie muszą dopasowywać wiersze między tabelami jeden do jednego, np. Używając klucza obcego vs. klucza podstawowego.
Colm Bhandal

Jak połączyć 2 stoły bez dopasowania do rzędu? Musisz mieć kolumnę klucz podstawowy lub obcy lub jakieś wspólne pole, aby móc wykonać łączenie. Zastanawiam się, dlaczego głosowałeś na tę odpowiedź. A diagram Venna jest źródłem wyjaśniającym, jak działa JOIN SQL. Czy masz jakieś lepsze przykłady do reprezentowania złączeń? Jeśli nie, proszę głosować za nią, aby ludzie mogli znaleźć lepsze rozwiązania. Dziękuję Ci.
Mayur

To ty umieszczasz diagramy w poście. Jaka jest legenda do diagramów? - Jakie są elementy każdego zestawu? A co z tym, że stoły to torby, a nie zestawy? Nie mów Jedną z rzeczy, których nie są zestawami, są rzędy A i B na etykietach. Zobacz moje komentarze do postów na tej stronie. Ten post po prostu na ślepo powtarza niewłaściwe użycie widoczne gdzie indziej, ale nie zrozumiane ani nie przesłuchane. Również to, co mówisz w tekście, jest niejasne i błędne. Również nie dodaje nic do wielu odpowiedzi już tutaj. (Chociaż prawie wszystkie są dość słabe.) PS Wyjaśnij za pomocą edycji, a nie komentarzy.
philipxy

FK nie są potrzebne, aby dołączyć lub wysłać zapytanie. Dowolne 2 tabele można łączyć pod dowolnym warunkiem obejmującym ich kolumny i niezależnie od jakichkolwiek ograniczeń, wyzwalaczy lub asercji.
philipxy

3
  • 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


1
Jest to zarówno złe, jak i niejasne. Łączenie nie jest przecięciem, chyba że tabele mają te same kolumny. Sprzężenia zewnętrzne nie mają wierszy z A lub B, chyba że mają te same kolumny, w którym to przypadku nie są dodawane null. Próbujesz coś powiedzieć, ale nie mówisz tego. Nie wyjaśniasz poprawnie ani jasno.
philipxy

@philipxy: Nie zgodziłem się na twoje oświadczenie Join is not an intersection unless the tables have the same columnsNie. Możesz dołączyć dowolne kolumny, a jeśli wartość będzie zgodna, połączą się one ze sobą.
SuicideSheep 11.04.17

Ten komentarz jest tak niejasny jak twoja odpowiedź. (Przypuszczam, że możesz myśleć coś takiego: zestaw wartości subrow dla wspólnych kolumn wyniku jest przecięciem zestawów wartości subrow dla wspólnych kolumn każdego z danych wejściowych; ale to nie to, co napisałeś. nie są jasne.)
philipxy 11.04.17

Miałem na myśli to, że łączenie jest tylko przecinaniem danych wejściowych, gdy jest naturalnym wewnętrznym łączeniem danych wejściowych z tymi samymi kolumnami. Używasz błędnie słów „skrzyżowanie” i „związek”.
philipxy

3

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

wyjście 1

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

wyjście 2

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.

łączy się

Zalety połączeń

  1. Wykonuje się szybciej.

2
Jest to poprawne tylko wtedy, gdy tabele mają ten sam zestaw kolumn. (Łączy łączenie wewnętrzne ze skrzyżowaniem i pełne łączenie ze złączem.) Również „dopasowanie” jest niezdefiniowane. Przeczytaj moje inne komentarze.
philipxy

2

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

Przyłączenie wewnętrzne:

Najczęściej napisane jako DOŁĄCZ w zapytaniach SQL. Zwraca tylko pasujące rekordy między tabelami.

Znajdź wszystkich pracowników i ich nazwy działów:

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, Josenie jest drukowane z EMP w danych wyjściowych, ponieważ dept_id 6nie znajduje dopasowania w tabeli działu. Podobnie, HRa R&Dwiersze 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.

LEWA DOŁĄCZ:

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.

HRi R&Dwiersze 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 .


2

Ogólny pomysł

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 JOINi LEFT OUTER JOIN.

Te dwie tabele stanowią podstawę do przedstawienia JOINponiższych s:

Podstawa

KRZYŻ DOŁĄCZ

CrossJoin

SELECT *
  FROM citizen
 CROSS JOIN postalcode

Rezultatem będą produkty kartezjańskie wszystkich kombinacji. Nie JOINwymaga warunek:

CrossJoinResult

DOŁĄCZ DO WEWNĘTRZNEGO

INNER JOIN jest taki sam jak po prostu: JOIN

InnerJoin

SELECT *
  FROM citizen    c
  JOIN postalcode p ON c.postal = p.postal

Rezultatem będą kombinacje, które spełniają wymagany JOINwarunek:

InnerJoinResult

DOŁĄCZ DO LEWEGO ZEWNĘTRZNEGO

LEFT OUTER JOIN jest taki sam jak LEFT JOIN

LeftJoin

SELECT *
  FROM citizen         c
  LEFT JOIN postalcode p ON c.postal = p.postal

Rezultatem będzie wszystko, citizennawet jeśli nie będzie żadnych dopasowań postalcode. Ponownie JOINwymagany jest warunek:

LeftJoinResult

Dane do gry

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;

Rozmyte granice podczas gry z JOINiWHERE

KRZYŻ DOŁĄCZ

CROSS JOINw 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 JOINdo uzyskania wyniku LEFT OUTER JOINwymaga sztuczek, takich jak dodawanie z NULLrzędu. Zostało pominięte

DOŁĄCZ DO WEWNĘTRZNEGO

INNER JOINstaje 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 JOINdo uzyskania wyniku LEFT OUTER JOINrównież wymaga sztuczek. Zostało pominięte

DOŁĄCZ DO LEWEGO ZEWNĘTRZNEGO

LEFT JOINwyniki 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 JOINwyniki 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

Problemy ze schematem Venna

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 Areprezentuje zestaw po lewej stronie ( citizentabela), a zestaw Bjest zestawem po prawej stronie ( postalcodetabela) w poniższej dyskusji.

KRZYŻ DOŁĄCZ

Każdy element w obu zestawach jest dopasowany do każdego elementu w drugim zestawie, co oznacza, że ​​potrzebujemy Ailości każdego Belementu i Bilości każdego Aelementu, 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 UNIONw ogóle nie pasuje.

Rzędy są różne. UNIONJest 7 rzędów w całości. Ale są niekompatybilne dla wspólnego SQLzestawu wyników. I wcale tak nie CROSS JOINdziała:

CrossJoinUnion1

Próbuję to przedstawić w następujący sposób:

CrossJoinUnion2Crossing

.. ale teraz wygląda to jak coś INTERSECTION, co z pewnością nie jest . Co więcej, nie ma w nim żadnego elementu, INTERSECTIONktóry byłby w żadnym z dwóch odrębnych zestawów. Wygląda jednak bardzo podobnie do wyników wyszukiwania podobnych do tego:

CrossJoinUnionUnion3

Dla porównania, jeden wynik wyszukiwania dla CROSS JOINs można zobaczyć na Tutorialgateway . Tak INTERSECTIONjak ten, jest pusty.

DOŁĄCZ DO WEWNĘTRZNEGO

Wartość elementu zależy od JOINwarunku. Można to przedstawić pod warunkiem, że każdy wiersz stanie się unikalny dla tego warunku. Znaczenie id=xjest prawdziwe tylko dla jednego wiersza. Gdy wiersz w table A( citizen) pasuje do wielu wierszy w table B( postalcode) pod JOINwarunkiem, 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 JOINwarunek określa umiejscowienie elementu na diagramie. Patrząc tylko na wartości JOINwarunku wraz z resztą rzędu tuż przed jazdą:

InnerJoinIntersection - Filled

Reprezentacja ta znajduje się całkowicie od siebie przy używaniu INNER JOINw ON 1 = 1stanie ją sporządza się na klasę CROSS JOIN.

W przypadku self- JOINwiersze są w rzeczywistości identycznymi elementami w obu tabelach, ale reprezentują tabele jako oba Ai Bnie są zbyt odpowiednie. Na przykład powszechnym JOINwarunkiem własnym , który sprawia, że ​​element Ajest dopasowywany do innego elementu w B, jest ON A.parent = B.childdopasowanie od Ado Bna osobnych elementach. Z przykładów, które wyglądałyby SQLtak:

SELECT *
  FROM citizen c1
  JOIN citizen c2 ON c1.id = c2.leader

SelfJoinResult

Znaczenie Smith jest liderem zarówno Green, jak i Jensen.

DOŁĄCZ DO ZEWNĄTRZ

Ponownie problemy zaczynają się, gdy jeden wiersz ma wiele dopasowań do wierszy w drugiej tabeli. Jest to dodatkowo skomplikowane, ponieważ OUTER JOINmożna dopasować pusty zestaw. Ale w teorii zbiorów połączenie dowolnego zbioru Ci pustego zbioru jest zawsze sprawiedliwe C. Pusty zestaw nic nie dodaje. Reprezentacja tego LEFT OUTER JOINzwykle pokazuje po prostu wszystko, Aaby zilustrować, że wiersze w Asą 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:

LeftJoinIntersection - Filled

GDZIE klauzula - sens

Znajdowanie wszystkich wierszy za CROSS JOINpomocą Smitha i kodu pocztowego na Księżycu:

SELECT *
  FROM citizen          c
 CROSS JOIN postalcode  p
 WHERE c.name = 'Smith'
   AND p.area = 'Moon';

Gdzie - wynik

Teraz diagram Venna nie jest używany do odzwierciedlenia JOIN. Jest używany tylko w przypadku WHEREklauzuli:

Gdzie

... i to ma sens.

Kiedy INTERSECT i UNION mają sens

KRZYŻOWAĆ

Jak wyjaśniono, INNER JOINtak naprawdę nie jest INTERSECT. Jednak INTERSECTmogą 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 SQLto 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';

UNIA

An OUTER JOINnie jest UNION. Pracuj jednak UNIONw tych samych warunkach co INTERSECT, co powoduje zwrócenie wszystkich wyników łączących oba SELECTs:

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:

Unia - Wynik

Również tutaj schemat Venna ma sens:

UNIA

Kiedy to nie dotyczy

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 UNIONdaje

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.


1

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 JOINsprowadzają się do dwóch przypadków:

W przypadku SELECTpodzbioru danych A:

  • użyj, INNER JOINgdy powiązane dane B, których szukasz, MUSZĄ istnieć według projektu bazy danych;
  • używaj, LEFT JOINgdy powiązane dane B, których szukasz, MOCĄ lub MOCĄ NIE istnieją zgodnie z projektem bazy danych.

1

Różnica między inner joini outer joinjest następująca:

  1. Inner joinjest złączeniem, które łączy tabele oparte na dopasowujących krotkach, podczas gdy outer joinjest złączeniem, które łączy tabele oparte na dopasowanej i niepasującej krotce.
  2. Inner joinscala dopasowany wiersz z dwóch tabel, w którym pomijany jest niedopasowany wiersz, natomiast outer joinscala wiersze z dwóch tabel i niepasujące wiersze wypełniają się wartością null.
  3. Inner joinjest jak operacja przecięcia, podczas gdy outer joinjest jak operacja związkowa.
  4. Inner jointo dwa typy, podczas gdy outer joinsą trzy typy.
  5. outer joinjest szybszy niż inner join.

1
Wynik łączenia zewnętrznego jest taki sam jak połączenie wewnętrzne, ale plus kilka dodatkowych wierszy, więc nie mam pojęcia, dlaczego uważasz, że połączenie zewnętrzne byłoby szybsze. Jakie są te „dwa rodzaje” złączenia wewnętrznego? Przypuszczam, że masz na myśli pełny, lewy i prawy zewnętrzny?
Martin Smith

1
@ M.achaibou Proszę nie wprowadzać zmian, które wprowadzają niepotrzebne zmiany formatu. Nazwy operatorów nie są kodami, chyba że są używane w kodzie. Proszę nie wprowadzać zmian do oznaczania postów, komentować autora. Jeśli nie masz przedstawiciela, poczekaj, aż to zrobisz. Zdarza się, że plakat zatwierdził to, ale proszę nie wprowadzać takich zmian. Łączenie zewnętrzne PS nie jest szybsze niż łączenie wewnętrzne.
philipxy
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.