3.7 内部結合と外部結合
employees テーブルには, department_id が欠損となっているレコードが1件あります. そのため, departments のどのレコードとも紐付かず, 結果からは脱落してしまいます. 社員全員を出力したいので, 部署名が紐付かないレコードであっても出力したいという場合はどうすればよいでしょうか? 単純に考えると, ON 句に条件を追加すれば良いように思えますが, LEFT JOIN 句を使うのが最も簡単です.
SELECT t1.id, t1.name, t2.name as department
FROM <DB>.employees t1
LEFT JOIN <DB>.departments t2
ON t1.department_id = t2.idLEFT JOIN 句は正確には LEFT OUTER JOIN と書きますが, OUTER は省略可能です. 内部結合に対し, この結合は, 左 (外部) 結合と呼ばれます. FROM 句の後指定したテーブルが「左」テーブルで, LEFT JOIN 句の後に書かれたテーブルが「右」テーブルになります. 左結合とは, デカルト集合のうち, ON 句の条件に一致するか, 左テーブルに存在するレコードを全て残す, という意味になります. 同様に, 「右」テーブルにあるものを条件一致するかにかかわらず全て出力したい場合は, 右 (外部) 結合を RIGHT (OUTER) JOIN 句を用いて実行します. 条件に紐付かなくても左右どちらかに存在するものを全て出力したい場合の結合は完全外部結合と呼ばれ, FULL (OUTER) JOIN 句を使います10. 以上の機能は ON 句に指定した条件にのみ適用され, WHERE 句に指定した条件は外部結合・内部結合を考慮しません. つまり, 外部結合の場合は「ON 句に指定した条件または 左 (右) テーブルに存在する」という条件づけがされていることになります.
内部結合と外部結合は, 数学の集合で習ったような, ベン図, 図3.2 をイメージするとわかりやすいです.
図 3.2: ベン図
3.7.1 COALESCE() 関数
外部結合ではしばしば欠損が発生します. 欠損をゼロで埋めるなど, 体裁を整えるのには COALESCE() 関数が便利です. 例えば今回の例では, 部署名が紐付かないレコードがあります. これを空白ではなく, 「不明」という文言に置き換えたい場合, 以下のようにします.
SELECT t1.id, t1.name, COALESCE(t2.name, '不明') AS department
FROM <DB>.employees t1
LEFT JOIN <DB>.departments t2
ON t1.department_id = t2.idCOALESCE() 関数は, 複数の引数の値のうち, 欠損でない, 最も左の値を返す関数です. よって上記のクエリでは t2.name が欠損でないレコードでは t2.name を返し, 欠損ならば ‘不明’ を返しています.
デカルト積は全ての組み合わせであるのに対して, 完全外部結合は, 結合キーの欠落したレコードを残すだけであって, 結合キーの一致しないレコードは除外されることに気をつけてください.↩︎