SQL を理解するうえで大切なのは、適切な問いを立てることです。複数のテーブルにまたがるデータを扱う場合、フルアウタージョインは間違いなく便利な操作です。一部のデータベース管理システムではごく一般的ですが、MySQL では FULL OUTER JOIN の扱いが少し厄介です。なぜでしょうか?標準ではサポートされていないからです。興味深いですよね?でもご安心ください、回避策があります!
このチュートリアルでは、MySQL でフルアウタージョインを実装する方法を詳しく見ていきます。準備はいいですか?たくさんのコード例に飛び込んでいきましょう。
🔖 クイックリファレンス: すべての JOIN の種類をすぐに確認したいですか?図解とコード例を掲載した SQL JOIN チートシートをご覧ください。
Full Outer Join とは?
始める前に、FULL OUTER JOIN とは何かを定義しておきましょう。SQL におけるフルアウタージョインは、左外部結合と右外部結合の両方を適用した効果を組み合わせたものです。つまり、両方のテーブルで値が一致するレコードに加えて、もう一方のテーブルに一致する値がない両テーブルのすべてのレコードも取得します。
例を見てみましょう。Employees と Departments という 2 つのテーブルがあるとします。
Employees テーブル:
| id | name |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
Departments テーブル:
| id | department |
|---|---|
| 2 | HR |
| 3 | IT |
| 4 | Marketing |
FULL OUTER JOIN クエリを使用すると:
SELECT * FROM Employees
FULL OUTER JOIN Departments ON Employees.id = Departments.id;
結果セットは次のようになります:
| Employees.id | Employees.name | Departments.id | Departments.department |
|---|---|---|---|
| 1 | Alice | NULL | NULL |
| 2 | Bob | 2 | HR |
| 3 | Charlie | 3 | IT |
| NULL | NULL | 4 | Marketing |
この出力は、Employees と Departments の両方のすべてのレコードを組み合わせたものです。含まれるのは次のとおりです:
- 両方のテーブルで
idの値が一致するレコード(Bob と Charlie)。 Departmentsに対応するレコードがないEmployeesのレコード(Alice)。Employeesに対応するレコードがないDepartmentsのレコード(Marketing)。
非常に便利な構文ですが、MySQL では直接サポートされていません。では、どうすればよいのでしょうか?見ていきましょう。
MySQL で Full Outer Join を再現する
前述のとおり、MySQL は FULL OUTER JOIN キーワードを明示的にはサポートしていません。しかし、LEFT JOIN と UNION を組み合わせることで、同じ出力を得ることができます
MySQL でフルアウタージョインを再現する考え方は、次の 2 つのステップから成ります:
- 1 つ目のテーブルに対して
LEFT JOINを実行し、1 つ目のテーブルのすべてのレコードと、2 つ目のテーブルの一致するレコードを取得します。 UNIONを使って、その結果をRIGHT JOINの結果と組み合わせ、2 つ目のテーブルのすべてのレコードと、1 つ目のテーブルの一致するレコードを取得します。
それぞれの要素の仕組みは次のとおりです:
Left Join:
Right Join:
MySQL の Full Outer Join の例
先ほどと同じデータを使った回避策の例を示します
SELECT
Employees.id AS Employees_id,
Employees.name,
Departments.id AS Departments_id,
Departments.department
FROM
Employees
LEFT JOIN
Departments ON Employees.id = Departments.id
UNION
SELECT
Employees.id AS Employees_id,
Employees.name,
Departments.id AS Departments_id,
Departments.department
FROM
Departments
RIGHT JOIN
Employees ON Departments.id = Employees.id;
このクエリは 2 つの部分で構成されています:
LEFT JOINで、Employeesテーブルのすべてのレコードと、Departmentsテーブルの一致するレコードを取得します。RIGHT JOINで、Departmentsテーブルのすべてのレコードと、Employeesテーブルの一致するレコードを取得します。
UNION は、重複する行を除外しながらこの 2 つのクエリの結果を結合します。
同じサンプルテーブルの場合、結果セットは次のようになります:
| Employees_id | name | Departments_id | department |
|---|---|---|---|
| 1 | Alice | NULL | NULL |
| 2 | Bob | 2 | HR |
| 3 | Charlie | 3 | IT |
| NULL | NULL | 4 | Marketing |
この出力は、SQL の FULL OUTER JOIN と同様に、Employees と Departments の両方のすべてのレコードを組み合わせたものです。
UNION は重複を自動的に除外する
Employees テーブルと Departments テーブルを使った今回の例では、MySQL で FULL OUTER JOIN を再現する回避策に使った UNION によって重複が生じることはありません。UNION 演算子は、結果セットから重複する行を自動的に除外するためです。
わかりやすくするために、この場合に UNION がどのように動作するかを考えてみましょう:
-
クエリの前半(
LEFT JOIN)は、Employees テーブルのすべてのレコードと、Departments テーブルの一致するレコードを取得します。これには、両方のテーブルで id の値が一致する行と、Departments に一致するものがない Employees の行が含まれます。 -
クエリの後半(
RIGHT JOIN)は、Departments テーブルのすべてのレコードと、Employees テーブルの一致するレコードを取得します。これには、両方のテーブルで id の値が一致する行と、Employees に一致するものがない Departments の行が含まれます。
UNION は重複を取り除くため、id の値が一致する行(LEFT JOIN と RIGHT JOIN の両方の結果に現れる行)は、最終結果に一度だけ表示されます。
まとめると、この場合に UNION を使うことで、Employees と Departments のデータの一意な組み合わせが結果セットに一度だけ現れるようになり、重複のない FULL OUTER JOIN の動作を再現できます。
Beekeeper Studio で練習しよう
この MySQL フルアウタージョインのチュートリアルがお役に立てば幸いです。今後の記事でも、MySQL のその他の高度な機能を取り上げ、さらに多くのコード例を紹介しながら、それらの機能がなぜ、どのように動作するのかを深く掘り下げていきます。それまでは、ぜひ Beekeeper Studio を使って SQL スキルを磨き続けてください。
Beekeeper Studioは無料のオープンソースのデータベースGUIです
これまで使った中で最高のSQLクエリ&エディタツールです。データベースの管理に必要なものがすべて揃っています。 - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studioは高速で直感的、そして使いやすいツールです。多数のデータベースに対応し、Windows、Mac、Linuxで快適に動作します。
Beekeeper Studio 利用者の声
「Beekeeper Studio で以前の SQL ワークフローを完全に置き換えました。高速で直感的で、データベース作業がまた楽しくなりました。」
「多くのデータベース GUI を試してきましたが、Beekeeper は機能とシンプルさのバランスが絶妙です。とにかくちゃんと動きます。」