VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
LEFT JOIN は一致の有無にかかわらず
左テーブルのすべての行を残します。これが、もう一方の問い、つまり何が一致
しなかったかに答える方法です。
始める前に mysql -u root -p sakila でクライアントを開いてください。
LEFT JOIN の仕組み
COLUMN_LIST を欲しい列に、LEFT_TABLE をすべての行を残したいテーブルに、
RIGHT_TABLE を追加の列を取り出すテーブルに、各 COLUMN_NAME をそれぞれの
側で両者をつなぐ列に置き換えます。
一致する行については、サーバーは内部結合として振る舞います。何にも一致
しない左の行については、その行をそのまま残し、右テーブルのすべての列を
NULL で埋めます。LEFT OUTER JOIN は同じ句を省略せずに書いたもので、
OUTER という語は何も加えません。
例
- 一致しない行を残す
Sakila には 6 つの言語があり、すべての映画は英語なので、5 つの言語はどの
映画にも一致しません。内部結合はそれらを除外します。この結合は除外しません。
- 何にも一致しなかった行だけを列挙する
本当の一致では決して NULL になりえない右テーブルの列に WHERE を加えると、
一致しなかった行だけがちょうど残ります。
f.film_id は film の主キーなので、一致した行には必ず値があります。そこが
NULL なのは、結合が何にも一致しなかった行を埋めた場合に限られます。右テーブルの
どの NOT NULL 列をテストしても同じ理屈が成り立ちます。主キーが最も安全な
選択です。どのテーブルでも NOT NULL だからです。
- 実務でこれが答える問い
カタログにあるすべての映画が棚にあるわけではありません。inventory は在庫を
保持するので、inventory の行がない映画は誰も借りられない映画です。
LEFT JOIN に WHERE <右のキー> IS NULL を加えたものが、あるテーブルの行の
うち別のテーブルに対応するものがない行を見つける方法です。
WHERE のフィルタは外部結合を打ち消す
これはLEFT JOIN で人が最も時間を失う間違いです。右テーブルに普通の条件を
加えるのは無害に見えます。
f.title が
NULL の 5 行を生成し、次に WHERE が各行をテストしますが、
NULL LIKE 'ACADEMY%' は真ではなく NULL なので、WHERE はそれらを除外します。
同じ条件を ON に移すと、何を一致とみなすかの一部になります。
LEFT JOIN では、右テーブルに対する
条件は ON に、左テーブルに対する条件は WHERE に置きます。唯一の意図的な
例外は例 2 の IS NULL で、この場合は一致した行を除外すること自体が目的です。
まとめ
- 一致の有無にかかわらず左テーブルのすべての行を残すには
LEFT JOINを使います。 - 何にも一致しなかった行では、右側のすべての列に NULL が入ります。
- 一致しなかった行だけを列挙するには、右テーブルの
NOT NULL列をIS NULLでテストします。 - 右テーブルに対する条件は
ONに置きます。WHEREに置くと一致しなかった行が除外されます。 LEFT OUTER JOINは同じ句の別の書き方です。
関連項目
- INNER JOIN — 一致だけを残す結合
- RIGHT JOIN — 同じ考え方を反対側から見たもの
- IS NULL — 一致しなかった行を見えるようにするテスト
- EXISTS — 結合を使わずに同じ問いを立てる
- MySQL の JOIN のパフォーマンスとよくある間違い — 同じ罠をバグ報告として見たもの