Jaka jest różnica między DOŁĄCZENIEM WEWNĘTRZNYM a DOŁĄCZENIEM DO ZEWNĘTRZNYM?


35

Jestem nowy w SQL i chciałem wiedzieć, jaka jest różnica między tymi dwoma JOINtypami?

SELECT * 
FROM user u
INNER JOIN telephone t ON t.user_id = u.id

SELECT * 
FROM user u
LEFT OUTER JOIN telephone t ON t.user_id = u.id

Kiedy powinienem użyć jednego lub drugiego?


6
czy to pasuje do pytania DBA? To wydaje mi się bardziej kodującym pytaniem.
BlackICE

1
@David swoje przemyślenia na temat Meta
Sathyajith Bhat

@David, a następnie VtC, jeśli uważasz, że to źle dla witryny. Zawsze możemy ponownie otworzyć.
jcolebrand

3
Myślę, że to świetne pytanie i bardzo odpowiednie dla witryny.
datagod

trzeba to wyprowadzić z DBA, chyba że noob DBA w rękawie, aby dostroić wydajność DB: P
AmDB

Odpowiedzi:


32
  • Sprzężenie wewnętrzne wybierze tylko te rekordy, w których połączone klucze znajdują się w obu określonych tabelach.
  • Lewe sprzężenie zewnętrzne będzie zaznaczyć wszystkie rekordy z pierwszej tabeli i wszelkie rekordy w drugiej tabeli, które odpowiadają złączone klucze.
  • Prawo sprzężenia zewnętrznego będzie zaznaczyć wszystkie rekordy z drugiej tabeli i wszelkie rekordy w pierwszej tabeli, które odpowiadają złączone klucze.

W pierwszym przykładzie zwrócisz listę użytkowników i numerów telefonów tylko wtedy, gdy dla użytkownika istnieje co najmniej jeden rekord telefoniczny.

W drugim przykładzie zwrócisz listę wszystkich użytkowników oraz wszelkie dane telefoniczne, jeśli są oni dostępni (jeśli nie są dostępni, otrzymasz NULLwartości telefoniczne).


13

Za każdym razem, gdy ktoś zadaje to pytanie, pojawia się odpowiedź: http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

Mam nadzieję, że pomoże ci to zrozumieć,


3
Pracuję z dołączeniami od 20 lat i te diagramy wydawały mi się mylące.
Hogan

3
Jestem z @Hogan - diagramy ven nie są najlepszym wytłumaczeniem tego .. siatka pokazująca, jakie kombinacje zostaną zwrócone, prawdopodobnie byłaby lepsza.
Joe

Wszystko, co pokazuje, to że nie rozumiesz schematu Venna. Odnoszą się one doskonale do rodzajów złączeń, ale należy pamiętać, że są narzędziem pomagającym zrozumieć nowe osoby dołączające. Jeśli nauczyłeś się już łączenia z myślą o innym pomyśle, to na pewno będzie ci to wyglądać obco. To nie jest problem, ale nie jest to również dobry wskaźnik przydatności diagramów.
JamesRyan

@jamesryan to nieprawda, nie łączą się idealnie, złączenia są podobne do kartezjańskiego iloczynu zestawów, a nie przecinania i łączenia, analog diagramu Venna działa tylko, jeśli łączysz się nad unikalnymi kluczami, jeśli masz zduplikowane klucze, to tracisz aspekt produktu kartezjańskiego.
Czy

1
Zdecydowanie się nie zgadzam, diagramy Venna mają już bardzo dobrze zdefiniowaną interpretację, zestaw przecięcia i połączenia. Połączenia nie pasują do tej interpretacji, gdy łączysz się z kluczami nie unikatowymi. Myślę, że interpretujesz diagramy Venna zbyt szeroko.
Czy

8

Sprzężenia wewnętrznego zostaje przywrócone rzędów, które mogą być łączone na podstawie łączą kryteriów.
Sprzężenie zewnętrzne zwraca te i wszystkie wiersze ...
   ... z pierwszego stołu dla lewego złączenia
   ... z drugiego stołu dla prawego złączenia
   ... z obu tabel dla pełnego złączenia

Wybór, kiedy użyć jednego lub drugiego, jest kwestią ustalenia, jakich danych potrzebujesz. Na przykład, jeśli potrzebujesz tylko rekordów zawierających identyfikatory użytkownika z telefonu, które pasują do identyfikatora użytkownika, użyj sprzężenia wewnętrznego. Jeśli chcesz również dołączyć wiersze od użytkownika, które nie mają pasującego wpisu telefonicznego, odpowiednie byłoby lewe łączenie.

Aby uzyskać więcej informacji zobacz to pytanie na StackOverflow .


7

Jeśli masz 2 tabele jak poniżej:

Table1 :   A1    B1          Table2  :    B2     C2 
           -     -                        -      -
           1     2                        1      1
           2     4                        2      4
           3     5                        5      2

Jeśli użyjesz funkcji dołączenia wewnętrznego, otrzymasz:

 A1     B1     B2      C2  
 -      -      -       -
 1      2      2       4
 3      5      5       2

Jeśli użyjesz Full Outer Join, otrzymasz:

 A1     B1     B2      C2  
 -      -      -       -
 1      2      2       4
 3      5      5       2
 2      4    NULL     NULL
NULL   NULL    1       1

Jeśli użyjesz Left Outer Join, otrzymasz:

 A1     B1     B2      C2  
 -      -      -       -
 1      2      2       4
 3      5      5       2
 2      4    NULL     NULL

6

Łączenie zewnętrzne jest wyraźnie zaprojektowane tak, aby dawało w wyniku wartości zerowe i dlatego należy go ogólnie unikać. Mówiąc relatywnie, jest to rodzaj małżeństwa ze strzelbą: zmusza stoły do ​​pewnego rodzaju związku - tak, mam na myśli związek, a nie przyłączanie się - nawet gdy dane tabele nie spełniają zwykłych wymagań dotyczących związku. Robi to w rzeczywistości, wypełniając jedną lub obie tabele zerami przed wykonaniem unii, dzięki czemu w końcu są one zgodne z tymi zwykłymi wymaganiami. Ale nie ma powodu, dla którego tego wypełnienia nie należy wykonywać przy użyciu odpowiednich wartości zamiast wartości zerowych, jak w tym przykładzie:

SELECT SNO , PNO 
FROM   SP 
UNION  
SELECT SNO , 'nil' AS PNO 
FROM   S 
WHERE  SNO NOT IN ( SELECT SNO FROM SP )

Alternatywnie ten sam wynik można uzyskać za pomocą operatora zewnętrznego łączenia SQL w połączeniu z COALESCE, jak tutaj:

SELECT SNO , COALESCE ( PNO , 'nil' ) AS PNO 
FROM ( S NATURAL LEFT OUTER JOIN SP ) AS TEMP

Uwaga na temat sprzężenia zewnętrznego (4.6) w „Teorii SQL i relacji: jak pisać dokładny kod SQL” według CJ Date


5

Łączenie wewnętrzne to łączenie, w którym wyświetlane są tylko wyniki, w których klucze znajdują się w obu tabelach. Sprzężenie zewnętrzne wyświetli wyniki dla wszystkich kluczy w jednej tabeli, lewe złączenie od pierwszego i prawe złączenie od drugiego. Na przykład:

Załóżmy, że tabela 1 zawiera następujące pary kluczy podstawowych i danych: (1, a), (2, b), (3, c)

Powiedzmy również, że tabela 2 ma następujące pary kluczy podstawowych i danych: (1, zabawa), (3, puszka), (4, zdarzenie)

Zatem wewnętrzne sprzężenie tabeli 1 z tabelą 2 na kluczach podstawowych dałoby następujące wynikowe tryplety (ze wspólnym kluczem podstawowym jako pierwszym, drugim elementem pierwszego stołu drugim i drugim elementem drugiego stołu trzecim): (1, a, fun), ( 3, c, puszka)

Lewe zewnętrzne połączenie tabeli 1 z tabelą 2 na kluczach podstawowych dałoby następujące wynikowe tryplety (taki sam format jak powyżej): (1, a, fun), (2, b, NULL), (3, c, can)

Prawe zewnętrzne połączenie tabeli 1 z tabelą 2 na kluczach podstawowych dałoby następujące wynikowe tryplety (taki sam format jak powyżej): (1, a, fun), (3, c, can), (4, NULL, happ)

Mam nadzieję, że to dobrze wyjaśnia tę koncepcję.


4

Pozwól mi spróbować opisać to nieco bardziej intuicyjnie.

Łączenie wewnętrzne pokazuje użytkowników, którzy mają jeden lub więcej telefonów wraz z ich numerami telefonicznymi.

Lewy zewnętrzny łącznik dodatkowo wymienia tych „użytkowników”, którzy nie mają telefonu.


4

Ponieważ zapytałeś, kiedy użyć czego, oto scenariusz z zapytaniami - wybierz, którego użyć w zależności od wymagań.

Dane:

Użytkownicy tabeli mają 10 rekordów. Tabela Phoneno ma 6 rekordów (z relacją 1: 1, co oznacza, że ​​wpis w PhoneNo będzie odnosił się tylko do jednego wpisu w Użytkownicy, a tylko jeden wpis w PhoneNo może odnosić się do danego wpisu w Użytkownicy).

Wymaganie 1: Pokaż wszystkim użytkownikom ich numery telefonów. Zignoruj ​​użytkowników bez numeru telefonu.

Pytanie:

SELECT u.uid, u.name, p.phonno 
  FROM user u 
INNER JOIN phones p ON p.uid = u.uid

Wynik: pokazuje 6 użytkowników, którzy mają numer telefonu

Wymaganie 2: Pokaż wszystkim użytkownikom ich numer telefonu. Jeśli użytkownik nie ma wyświetlacza telefonu „Nie dotyczy” (niedostępne)

Pytanie:

SELECT u.uid, u.name, ifnull(p.phonno,'N/A') 
  FROM user u 
LEFT OUTER JOIN phones p ON p.uid = u.uid

Wynik:

Pokazuje wszystkie 10 rekordów

Uwaga: ifnull to składnia MySql do przekształcania wartości null. Użyłem tej funkcji, aby silnik db pokazywał „N / A”, gdy phonno ma wartość null. Poszukaj odpowiedniej funkcji, jeśli używasz innego DBMS. W SQL Server musisz użyć CASEinstrukcji.

Mam nadzieję, że to pomoże.

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.