Kiedy używać LEFT JOIN a kiedy INNER JOIN?

Czuję, że zawsze uczono mnie używać LEFT JOINs i często widzę je zmieszane z INNER s, aby wykonać ten sam typ zapytania w kilku kawałkach kodu, które mają robić to samo na różnych stronach. Idzie:

SELECT ac.reac, pt.pt_name, soc.soc_name, pt.pt_soc_code
FROM
  AECounts ac
  INNER JOIN 1_low_level_term llt on ac.reac = llt.llt_name
  LEFT JOIN 1_pref_term pt ON llt.pt_code = pt.pt_code
  LEFT JOIN 1_soc_term soc ON pt.pt_soc_code = soc.soc_code
LIMIT 100,10000

Nad tym właśnie pracuję:

Widzę wiele jak:

SELECT COUNT(DISTINCT p.`case`) as count
FROM FDA_CaseReports cr
  INNER JOIN ae_indi i ON i.isr = cr.isr
  LEFT JOIN ae_case_profile p ON cr.isr = p.isr
Wygląda na to, że lewa równie dobrze może być wewnętrzna.
 25
Author: Interrobang, 2012-03-21

4 answers

Jest jakiś haczyk? Tak, jest-lewe połączenia są formą zewnętrznego połączenia, podczas gdy wewnętrzne połączenia są formą, cóż, wewnętrznego połączenia.

Oto przykłady, które pokazują różnicę. Zaczniemy od danych bazowych:

mysql> select * from j1;
+----+------------+
| id | thing      |
+----+------------+
|  1 | hi         |
|  2 | hello      |
|  3 | guten tag  |
|  4 | ciao       |
|  5 | buongiorno |
+----+------------+

mysql> select * from j2;
+----+-----------+
| id | thing     |
+----+-----------+
|  1 | bye       |
|  3 | tschau    |
|  4 | au revoir |
|  6 | so long   |
|  7 | tschuessi |
+----+-----------+

I tutaj zobaczymy różnicę między łącznikiem wewnętrznym a łącznikiem lewym:

mysql> select * from j1 inner join j2 on j1.id = j2.id;
+----+-----------+----+-----------+
| id | thing     | id | thing     |
+----+-----------+----+-----------+
|  1 | hi        |  1 | bye       |
|  3 | guten tag |  3 | tschau    |
|  4 | ciao      |  4 | au revoir |
+----+-----------+----+-----------+

Hmm, 3 rzędy.

mysql> select * from j1 left join j2 on j1.id = j2.id;
+----+------------+------+-----------+
| id | thing      | id   | thing     |
+----+------------+------+-----------+
|  1 | hi         |    1 | bye       |
|  2 | hello      | NULL | NULL      |
|  3 | guten tag  |    3 | tschau    |
|  4 | ciao       |    4 | au revoir |
|  5 | buongiorno | NULL | NULL      |
+----+------------+------+-----------+
Wow, 5 rzędów! Co się stało?

Zewnętrzne połączenia, takie jak left join zachowują wiersze, które nie pasują -- więc wiersze o id 2 i 5 są zachowywane przez / align = "left" / Pozostałe Kolumny są wypełnione znakiem NULL.

Innymi słowy, połączenia lewe i wewnętrzne nie są wymienne.
 82
Author: Matt Fenwick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-21 03:14:55

Oto szorstka odpowiedź, Tak myślę o połączeniach. Mam nadzieję, że będzie to bardziej pomocne niż bardzo precyzyjna odpowiedź ze względu na wyżej wymienione problemy matematyczne... ;-)

Połączenia wewnętrzne zawężają zbiór wierszy zwracanych. Złączenia zewnętrzne (lewe lub prawe) nie zmieniają liczby zwracanych wierszy, ale po prostu "zbierają" dodatkowe kolumny, jeśli to możliwe.

W pierwszym przykładzie wynikiem będą wiersze z AECounts pasujące do warunków określonych w tabeli 1_low_level_term. Wtedy dla tych wiersze, to próbuje połączyć się z 1_pref_term i 1_soc_term. Ale jeśli nie ma dopasowania, wiersze pozostają, a połączone w kolumnach są null.

 9
Author: rob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-22 01:15:03

Połączenie wewnętrzne zwróci tylko wiersze, w których w obu tabelach znajdują się pasujące wartości, podczas gdy połączenie lewe zwróci wszystkie wiersze z lewej tabeli, nawet jeśli w prawej tabeli nie ma pasującego wiersza

Szybki przykład

TableA
ID   Value
1    TableA.Value1
2    TableA.Value2
3    TableA.Value3

TableB
ID   Value
2    TableB.ValueB
3    TableB.ValueC

Połączenie wewnętrzne tworzy:

SELECT a.ID,a.Value,b.ID,b.Value 
FROM TableA a INNER JOIN TableB b ON b.ID = a.ID

a.ID    a.Value            b.ID    b.Value
2       TableA.Value2      2       TableB.ValueB
3       TableA.Value3      3       TableB.ValueC

Lewy łącznik tworzy:

SELECT a.ID,a.Value,b.ID,b.Value 
FROM TableA a LEFT JOIN TableB b ON b.ID = a.ID

a.ID    a.Value            b.ID    b.Value
1       TableA.Value1      NULL    NULL
2       TableA.Value2      2       TableB.ValueB
3       TableA.Value3      3       TableB.ValueC

Jak widać, lewy łącznik zawiera wiersz z TableA, gdzie ID = 1, mimo że nie ma pasującego wiersza w TableB, gdzie ID = 1, natomiast wewnętrzny łącznik wyklucza wiersz, ponieważ nie ma pasującego wiersza w TableB

HTH

 5
Author: philf2b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-21 03:14:19

Użyj łącznika wewnętrznego, gdy chcesz, aby tylko wyniki wyświetlane w obu tabelach odpowiadały warunkowi łączenia.

Użyj lewego łącznika, gdy chcesz, aby wszystkie wyniki były wyświetlane w tabeli A, ale jeśli Tabela B zawiera dane istotne dla niektórych rekordów tabeli a, to chcesz również użyć tych danych w tym samym zapytaniu.

Użyj pełnego połączenia, gdy chcesz mieć wszystkie wyniki z obu tabel.

 1
Author: Seung Bae Im,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-04 05:13:08