Beispiel mit den Tabellen A und B:
A (parent) B (child)
============ =============
id | name pid | name
------------ -------------
1 | Alex 1 | Kate
2 | Bill 1 | Lia
3 | Cath 3 | Mary
4 | Dale NULL | Pan
5 | Evan
Wenn Sie Eltern und ihre Kinder finden möchten, führen Sie einen INNER JOIN
durch :
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent INNER JOIN child
ON parent.id = child.pid
Ergebnis ist, dass jede Übereinstimmung eines parent
id
von aus der linken Tabelle und ein child
's pid
aus der zweiten Tabelle wird im Ergebnis als Zeile angezeigt:
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
+----+--------+------+-------+
Nun, das Obige zeigt keine Eltern ohne Kinder (weil ihre IDs keine Übereinstimmung mit den IDs der Kinder haben, was tun Sie also? Sie führen stattdessen einen äußeren Join aus. Es gibt drei Arten von äußeren Joins, den linken, den rechten und der vollständige äußere Join. Wir brauchen den linken, da wir die "zusätzlichen" Zeilen aus der linken Tabelle (Elternteil) haben wollen:
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent LEFT JOIN child
ON parent.id = child.pid
Das Ergebnis ist, dass neben früheren Übereinstimmungen auch alle Eltern angezeigt werden, die keine Übereinstimmung haben (sprich:kein Kind haben):
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
| 2 | Bill | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
Woher kommen all diese NULL
komme aus? Nun, MySQL (oder jedes andere RDBMS, das Sie verwenden) wird nicht wissen, was es dort einfügen soll, da diese Eltern keine Übereinstimmung (Kind) haben, also gibt es kein pid
noch child.name
mit diesen Eltern zusammenzubringen. Also setzt es diesen speziellen Nicht-Wert namens NULL
.
Mein Punkt ist, dass diese NULLs
werden (in der Ergebnismenge) während des LEFT OUTER JOIN
erstellt .
Wenn wir also nur die Eltern anzeigen möchten, die KEIN Kind haben, können wir ein WHERE child.pid IS NULL
hinzufügen zum LEFT JOIN
Oben. Das WHERE
-Klausel wird nach dem JOIN
ausgewertet (überprüft). ist fertig. Aus dem obigen Ergebnis geht also hervor, dass nur die letzten drei Zeilen die pid
enthalten NULL ist, wird angezeigt:
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent LEFT JOIN child
ON parent.id = child.pid
WHERE child.pid IS NULL
Ergebnis:
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 2 | Bill | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
Was passiert nun, wenn wir IS NULL
verschieben überprüfen Sie von WHERE
zum Beitritt ON
Klausel?
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent LEFT JOIN child
ON parent.id = child.pid
AND child.pid IS NULL
In diesem Fall versucht die Datenbank, Zeilen aus den beiden Tabellen zu finden, die diesen Bedingungen entsprechen. Das heißt, Zeilen mit parent.id = child.pid
UND child.pid IN NULL
. Aber es kann keine solche Übereinstimmung finden weil keine child.pid
kann gleich etwas sein (1, 2, 3, 4 oder 5) und gleichzeitig NULL sein!
Also, die Bedingung:
ON parent.id = child.pid
AND child.pid IS NULL
entspricht:
ON 1 = 0
was immer False
ist .
Warum gibt es also ALLE Zeilen aus der linken Tabelle zurück? Weil es ein LEFT JOIN ist! Und Linksverknüpfungen geben Zeilen zurück, die übereinstimmen (in diesem Fall keine) und auch Zeilen aus der linken Tabelle, die nicht übereinstimmen der Scheck (alle in diesem Fall ):
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | NULL | NULL |
| 2 | Bill | NULL | NULL |
| 3 | Cath | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
Ich hoffe, die obige Erklärung ist klar.
Nebenbemerkung (nicht direkt mit Ihrer Frage verbunden):Warum um alles in der Welt Pan
nicht in keinem unserer JOINs auftauchen? Weil seine pid
ist NULL
und NULL in der (nicht gemeinsamen) Logik von SQL ist nicht gleich irgendetwas, also kann es nicht mit einer der übergeordneten IDs (die 1,2,3,4 und 5 sind) übereinstimmen. Selbst wenn dort eine NULL wäre, würde es immer noch nicht passen, weil NULL
ist mit nichts gleich, nicht einmal mit NULL
selbst (es ist in der Tat eine sehr seltsame Logik!). Deshalb verwenden wir die spezielle Prüfung IS NULL
und kein = NULL
prüfen.
Also Pan
erscheinen, wenn wir einen RIGHT JOIN
machen ? Ja, es wird! Weil ein RIGHT JOIN alle Ergebnisse anzeigt, die übereinstimmen (der erste INNER JOIN, den wir gemacht haben) plus alle Zeilen aus der RIGHT-Tabelle, die nicht übereinstimmen (was in unserem Fall einer ist, der (NULL, 'Pan')
Zeile.
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent RIGHT JOIN child
ON parent.id = child.pid
Ergebnis:
+------+--------+------+-------+
| id | parent | pid | child |
+---------------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
| NULL | NULL | NULL | Pan |
+------+--------+------+-------+
Leider hat MySQL keinen FULL JOIN
. Sie können es in anderen RDBMSs ausprobieren, und es wird angezeigt:
+------+--------+------+-------+
| id | parent | pid | child |
+------+--------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
| 2 | Bill | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
| NULL | NULL | NULL | Pan |
+------+--------+------+-------+