MySQL: Szybkie zestawienie typów złączeń


157

Chciałbym szybko zestawić typy złączeń MySQL. Wiem o tych, reszta nie jestem pewien, co mają na myśli.

  • oddzielone przecinkami (od czego dokładnie jest to skrót?):SELECT * FROM a, b WHERE b.id = a.beeId AND ...
  • pokaż informacje z a, nawet jeśli nie ma dopasowań w b: SELECT * FROM a LEFT OUTER JOIN b ON b.id = a.beeId WHERE ...

Widziałem inne łączenia, ale chcę wiedzieć, co je różni, co jest INNER/ OUTER, powoduje dodanie LEFTzmian.

Wiem już, jak działają łączenia, chcę tylko wiedzieć, czy istnieją inne typy połączeń, czy też są to po prostu różne sposoby uzyskania tego samego wyniku.


Odpowiedzi:


463

3
+1, ale brakuje obu cross join, co daje iloczyn kartezjański.
Denis de Bernardy

11
@denis: przyjrzyj się bliżej linkowi codinghorror.com:There's also a cartesian product or cross join, which as far as I can tell, can't be expressed as a Venn diagram:
Rufinus,

1
Jestem zdumiony, drukuję te diagramy i umieszczam je na ścianie w moim biurze. zmieniłeś moje życie!
yossico

41
Pytanie dotyczy w szczególności MySQL. MySQL nie obsługuje złączeń FULL OUTER.
Mike Baranczak

4
i oczywiście powinien to być powód, aby nie publikować tej grafiki. westchnienie
Rufinus

27

Opierając się na twoim komentarzu, proste definicje każdego typu najlepiej znaleźć w W3Schools Pierwsza linia każdego typu zawiera krótkie wyjaśnienie typu łączenia

  • JOIN: Zwraca wiersze, gdy jest co najmniej jedno dopasowanie w obu tabelach
  • LEFT JOIN: Zwróć wszystkie wiersze z lewej tabeli, nawet jeśli nie ma żadnych dopasowań w prawej tabeli
  • RIGHT JOIN: Zwróć wszystkie wiersze z prawej tabeli, nawet jeśli nie ma żadnych dopasowań w lewej tabeli
  • FULL JOIN: Zwraca wiersze, gdy w jednej z tabel występuje dopasowanie

KONIEC EDYCJI

W skrócie, podany przez ciebie przykład oddzielony przecinkami

SELECT * FROM a, b WHERE b.id = a.beeId AND ...

polega na zaznaczaniu każdego rekordu z tabel a i b przecinkami oddzielającymi tabele, można tego użyć również w kolumnach takich jak

SELECT a.beeName,b.* FROM a, b WHERE b.id = a.beeId AND ...

Następnie pobiera poinstruowane informacje w wierszu, w którym w przykładzie kolumny b.id i a.beeId pasują do siebie. W twoim przykładzie otrzyma wszystkie informacje z tabel a i b, gdzie b.id jest równe a.beeId. W moim przykładzie otrzyma wszystkie informacje z tabeli b i tylko informacje z kolumny a.beeName, gdy b.id jest równe a.beeId. Zauważ, że istnieje również klauzula AND, która pomoże zawęzić wyniki.

Aby zapoznać się z prostymi samouczkami i objaśnieniami dotyczącymi łączenia mySQL i łączenia lewostronnego, zapoznaj się z samouczkami Tizag dotyczącymi mySQL. Możesz również odwiedzić stronę internetową Keitha J. Browna, aby uzyskać więcej informacji na temat połączeń, które również są całkiem dobre.

mam nadzieję, że to Ci pomoże


Zdarza się, że już to wszystko wiem. Właściwie szukałem typów połączeń, które istnieją. Przepraszam, że nie było jasne, co już wiem. Ale nie szukałem długiej dokumentacji tylko po to, aby uzyskać szybkie podsumowanie.
Bryan Field

Kolejne odniesienie w odpowiedzi ... może być bardziej tym, czego chcesz, kolego.
Ryan

+1 dla tej zmiany. Nie jestem stronniczy w stosunku do W3Schools, jak się wydaje niektórym ludziom. Może nie widziałem zbyt wiele złych stron, a może to tylko „święta wojna”. Ponadto zredagowałem zawartość W3Schools, mam nadzieję, że nie masz nic przeciwko, ale nie krępuj się wprowadzać dowolne poprawki. Wszystkie te wizualizacje w akceptowanej odpowiedzi są ładne, ale niektóre są w rzeczywistości odmianami tego samego łączenia. To dobra alternatywa.
Bryan Field

Dzięki George, nie mam nic przeciwko, pod warunkiem, że edycja jest poprawna! Jestem przekonany, że ludzie muszą znaleźć odpowiednie dla siebie źródła, mniej lub więcej informacji, wiele przykładów lub żadnych. W3Schools mają dokładne i zwięzłe, mają też dobre przykłady, Tizag jest podobny. Spokojnie kolego
Ryan

1
w mysql nie ma FULL JOIN, więc te linki nie są zbyt przydatne.
Eter

13

Mam 2 takie tabele:

> SELECT * FROM table_a;
+------+------+
| id   | name |
+------+------+
|    1 | row1 |
|    2 | row2 |
+------+------+

> SELECT * FROM table_b;
+------+------+------+
| id   | name | aid  |
+------+------+------+
|    3 | row3 |    1 |
|    4 | row4 |    1 |
|    5 | row5 | NULL |
+------+------+------+

INNER JOIN dba o oba stoły

INNER JOIN dba o obie tabele, więc otrzymujesz wiersz tylko wtedy, gdy obie tabele mają jeden. Jeśli jest więcej niż jedna pasująca para, otrzymasz wiele wierszy.

> SELECT * FROM table_a a INNER JOIN table_b b ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | id   | name | aid  |
+------+------+------+------+------+
|    1 | row1 |    3 | row3 | 1    |
|    1 | row1 |    4 | row4 | 1    |
+------+------+------+------+------+

Nie ma znaczenia dla INNER JOIN, jeśli odwrócisz kolejność, ponieważ zależy to na obu tabelach:

> SELECT * FROM table_b b INNER JOIN table_a a ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    4 | row4 | 1    |    1 | row1 |
+------+------+------+------+------+

Otrzymujesz te same wiersze, ale kolumny są w innej kolejności, ponieważ wspomnieliśmy o tabelach w innej kolejności.

LEFT JOIN dba tylko o pierwszy stół

LEFT JOIN dba o pierwszą tabelę, którą mu podasz, i nie przejmuje się zbytnio drugą, więc zawsze otrzymujesz wiersze z pierwszej tabeli, nawet jeśli nie ma odpowiadającego wiersza w drugiej:

> SELECT * FROM table_a a LEFT JOIN table_b b ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | id   | name | aid  |
+------+------+------+------+------+
|    1 | row1 |    3 | row3 | 1    |
|    1 | row1 |    4 | row4 | 1    |
|    2 | row2 | NULL | NULL | NULL |
+------+------+------+------+------+

Powyżej możesz zobaczyć wszystkie wiersze tabeli table_a, mimo że niektóre z nich nie pasują do niczego w tabeli b, ale nie wszystkie wiersze tabeli table_b - tylko te, które pasują do czegoś w tabeli table_a.

Jeśli odwrócimy kolejność tabel, LEFT JOIN zachowuje się inaczej:

> SELECT * FROM table_b b LEFT JOIN table_a a ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    4 | row4 | 1    |    1 | row1 |
|    5 | row5 | NULL | NULL | NULL |
+------+------+------+------+------+

Teraz otrzymujemy wszystkie wiersze tabeli table_b, ale tylko pasujące wiersze tabeli table_a.

RIGHT JOIN dba tylko o drugi stół

a RIGHT JOIN bdostajesz dokładnie te same wiersze, co b LEFT JOIN a. Jedyną różnicą jest domyślna kolejność kolumn.

> SELECT * FROM table_a a RIGHT JOIN table_b b ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | id   | name | aid  |
+------+------+------+------+------+
|    1 | row1 |    3 | row3 | 1    |
|    1 | row1 |    4 | row4 | 1    |
| NULL | NULL |    5 | row5 | NULL |
+------+------+------+------+------+

To są te same rzędy table_b LEFT JOIN table_a, które widzieliśmy w sekcji LEFT JOIN.

Podobnie:

> SELECT * FROM table_b b RIGHT JOIN table_a a ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    4 | row4 | 1    |    1 | row1 |
| NULL | NULL | NULL |    2 | row2 |
+------+------+------+------+------+

To te same rzędy, co table_a LEFT JOIN table_b.

Żadne połączenie w ogóle nie daje kopii wszystkiego

Bez klauzuli Join: Jeśli piszesz tabele bez klauzuli JOIN, oddzielone przecinkami, otrzymasz każdy wiersz pierwszej tabeli zapisany obok każdego wiersza drugiej tabeli, w każdej możliwej kombinacji:

> SELECT * FROM table_b, table_a;        
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    3 | row3 | 1    |    2 | row2 |
|    4 | row4 | 1    |    1 | row1 |
|    4 | row4 | 1    |    2 | row2 |
|    5 | row5 | NULL |    1 | row1 |
|    5 | row5 | NULL |    2 | row2 |
+------+------+------+------+------+

(To jest z mojego wpisu na blogu Przykłady typów sprzężeń SQL )


@Anu Proszę, nie rób tak trywialnych zmian, kiedy Twoja słaba reputacja oznacza, że ​​Twoje zmiany muszą zostać sprawdzone przez innych, po prostu tracisz ich czas. Ta zmiana powinna zostać odrzucona jako żadna różnica. Kod, który zmieniłeś, nie był w rzeczywistości zły i mogłeś skomentować.
philipxy

@philipxy Okay. Zauważyłem z tym. Kiedy próbowałem zrozumieć wyjaśnienie, zobaczyłem taką literówkę i dlatego zredagowałem, aby było jaśniejsze. Rzeczywiście, jest to dobra odpowiedź i moim zamiarem było, aby była bardziej poprawna.
Anu

@Anu Ta odpowiedź ma takie same fragmentaryczne, niepełne opisy, jak w większości odpowiedzi. W rzeczywistości nie mówi, jakie jest wyjście jako funkcja danych wejściowych. Zobacz także prawie każdą odpowiedź w proponowanym duplikacie i moje komentarze na obu stronach. Zobacz także moją odpowiedź tam. PS Widziałem to od wczoraj, ponownie sprawdziłem rozmiar edycji (oczywiście jest o wiele więcej powiązanych postów na Meta Stack Overflow i Meta Stack Exchange .)
philipxy

11

Pełne sprzężenie zewnętrzne nie istnieje w mysql, może być konieczne użycie kombinacji złączenia lewego i prawego.

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.