テーブルAと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
親とその子供を見つけたい場合は、INNER JOIN
を実行します :
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent INNER JOIN child
ON parent.id = child.pid
結果は、parent
のすべての一致です のid
左のテーブルとchild
から のpid
2番目のテーブルの結果に行として表示されます:
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
+----+--------+------+-------+
さて、上記は子供がいない親を示していません(彼らのIDは子供のIDと一致しないため、どうしますか?代わりに外部結合を行います。外部結合には、左、右、および3つのタイプがあります。完全な外部結合。左側のテーブル(親)からの「余分な」行が必要なため、左側の結合が必要です。
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent LEFT JOIN child
ON parent.id = child.pid
その結果、以前の試合に加えて、試合がない(読む:子供がいない)すべての親も表示されます:
+----+--------+------+-------+
| 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
はどこにありましたか から来る?そうですね、MySQL(または使用する可能性のある他のRDBMS)は、これらの親に一致するもの(子)がないため、そこに何を配置するかわかりません。したがって、pid
はありません。 また、child.name
それらの両親と一致するために。したがって、NULL
と呼ばれるこの特別な非値を配置します 。
私のポイントは、これらのNULLs
LEFT OUTER JOIN
中に(結果セットに)作成されます 。
したがって、子供がいない親のみを表示する場合は、WHERE child.pid IS NULL
を追加できます。 LEFT JOIN
へ その上。 WHERE
JOIN
の後に句が評価(チェック)されます 終わらせる。したがって、上記の結果から、pid
が存在する最後の3行のみであることが明らかです。 NULLが表示されます:
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
結果:
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 2 | Bill | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
さて、そのIS NULL
を移動するとどうなりますか WHERE
から確認してください 参加するON
に 条項?
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
この場合、データベースはこれらの条件に一致する2つのテーブルから行を見つけようとします。つまり、parent.id = child.pid
である行 そして child.pid IN NULL
。しかし、そのような一致は見つかりません child.pid
がないため 何か(1、2、3、4、または5)と等しく、同時にNULLにすることができます!
したがって、条件:
ON parent.id = child.pid
AND child.pid IS NULL
と同等です:
ON 1 = 0
これは常にFalse
。
では、なぜ左側のテーブルからすべての行を返すのでしょうか。 LEFT JOINだから! そして、左結合は一致する行(この場合はなし)を返します また、一致しない左側のテーブルの行 チェック(この場合はすべて ):
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | NULL | NULL |
| 2 | Bill | NULL | NULL |
| 3 | Cath | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
上記の説明が明確であることを願っています。
補足(あなたの質問に直接関係していません):なぜ地球上でPan
しないのですか? どのJOINにも表示されませんか?彼のpid
NULL
です SQLの(一般的ではない)ロジックのNULLは何にも等しくないため、親ID(1、2、3、4、および5)のいずれとも一致しません。そこにNULLがあったとしても、NULLs
であるため、一致しません。 NULLs
でさえも、何にも等しくありません それ自体(それは確かに非常に奇妙な論理です!)。そのため、特別なチェックIS NULL
を使用します = NULL
ではありません チェックしてください。
したがって、Pan
RIGHT JOIN
を実行すると表示されます ?はい、そうなります! RIGHT JOINは、一致するすべての結果(最初に行ったINNER JOIN)と、一致しないRIGHTテーブルのすべての行(この場合は1つ、(NULL, 'Pan')
行。
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent RIGHT JOIN child
ON parent.id = child.pid
結果:
+------+--------+------+-------+
| id | parent | pid | child |
+---------------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
| NULL | NULL | NULL | Pan |
+------+--------+------+-------+
残念ながら、MySQLにはFULL JOIN
がありません 。他のRDBMSで試すことができ、次のように表示されます:
+------+--------+------+-------+
| 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 |
+------+--------+------+-------+