【SQL】JOIN句の書き方と使い方の基本
SQLで複数のテーブルを結合するJOIN句の基本を、初心者向けに解説します。INNER JOINやLEFT JOINといった代表的な種類ごとの特徴と違いを、具体的なサンプルコードを交えて説明します。この記事を読めば、別々のテーブルから関連データを取り出す方法がわかります。
開発環境
- OS: Windows10
- DatabaseGUI: TablePlus
- MySQL: 8.0.42
JOIN句とは
JOIN句は、データベースに保存されている複数の表(テーブル)から、互いに関連のあるデータを見つけ出し、それらを一つに結合して取り出すためのSQLの命令(句)です。
データベースでは、情報を整理しやすくするために、例えば「顧客の情報をまとめたテーブル」と「注文履歴をまとめたテーブル」のように、データの種類ごとにテーブルを分けて管理することが一般的です。
しかし、分析や確認の際には「どの顧客が、いつ、何を注文したのか」といったように、複数のテーブルにまたがる情報を一度に確認したい場面が出てきます。
このようなときにJOIN句が役立ちます。JOIN句を使うと、「顧客番号」のような両方のテーブルに共通して存在するデータを手がかりにして、別々のテーブルにある情報を正しく結びつけることができます。
その結果、もともとは別々のテーブルに分かれていた情報が、あたかも一つの大きな表であるかのように、必要な情報がまとまった形式(結果セット)で取得できます。
JOIN句の基本構文
JOIN句は、複数のテーブルに分かれて保存されているデータを、関連する情報をもとに一つに結合して取得するための命令です。これにより、別々のテーブルにある情報を一度にまとめて見ることができます。
1SELECT 2 テーブルA.カラム名, 3 テーブルB.カラム名, 4 ... 5FROM 6 テーブルA 7JOIN テーブルB ON テーブルA.カラム名 = テーブルB.カラム名;
この構文は、以下の要素で構成されています。
-
SELECT テーブルA.カラム名, テーブルB.カラム名結合した結果から、どのテーブルのどのカラム(列)を表示したいかを指定します。テーブル名.カラム名の形式で書くことで、どのテーブルのカラムであるかを明確に区別します。 -
FROM テーブルA結合の基準となる、1つ目のテーブルを指定します。 -
JOIN テーブルBFROM句で指定したテーブルに結合したい、2つ目のテーブルを指定します。 -
ON テーブルA.カラム名 = テーブルB.カラム名2つのテーブルを結合するための条件を指定します。ここには、両方のテーブルに共通して存在するカラム(例えば、顧客IDや商品IDなど)を指定し、その値が一致する行同士を結びつけます。このON句で指定する条件が、JOIN句の最も重要な部分です。
JOINの種類と特徴
データベースから情報を取り出す際、複数のテーブル(表)を組み合わせて目的のデータを取得することがよくあります。このテーブル同士を結合する操作を「JOIN」と呼びます。ここでは、代表的なJOINの種類とその特徴を解説します。
INNER JOIN(インナージョイン / 内部結合)
- 2つのテーブルを結合する際、両方のテーブルに共通して存在するデータ(行)だけを取得します。
- 例えば、「社員テーブル」と「部署テーブル」を結合した場合、どちらにも存在する部署IDを持つ社員の情報だけが表示されます。
- 2つのテーブル間で、関連がある情報だけを厳選して見たい場合に使用します。
LEFT OUTER JOIN(レフトアウタージョイン / 左外部結合)
- 最初に指定したテーブル(左側のテーブル)のデータは、すべて表示されます。
- 左側のテーブルのデータに対して、関連するデータが右側のテーブルに存在しない場合、その部分は「NULL(ヌル)」という「データなし」を意味する値で表示されます。
- 「全社員の一覧」を基準にして、「所属部署名」を付け加えたい、といった場合に使います。このとき、部署に所属していない社員がいても、その社員情報は一覧に表示されます。
RIGHT OUTER JOIN(ライトアウタージョイン / 右外部結合)
- 後から指定したテーブル(右側のテーブル)のデータは、すべて表示されます。これはLEFT JOINの左右逆の動作です。
- 右側のテーブルのデータに対して、関連するデータが左側のテーブルに存在しない場合、その部分は「NULL」で表示されます。
- 「全部署の一覧」を基準にして、「所属している社員」を表示したい、といった場合に使います。社員が一人も所属していない部署も、一覧には表示されます。
FULL OUTER JOIN(フルアウタージョイン / 外部結合)
- 2つのテーブルにあるすべてのデータを、重複なく表示します。
- 片方のテーブルにしか存在しないデータの場合、もう片方のテーブルに対応する情報がない部分は「NULL」で補われます。
- 2つのテーブルの情報を、どちらも欠かすことなくすべて確認したい場合に使用します。
CROSS JOIN(クロスジョイン / 直積結合)
- 2つのテーブルのすべての行を、総当たりで組み合わせた結果を生成します。例えば、3行のテーブルと4行のテーブルをCROSS JOINすると、3 × 4 = 12行の結果が返ってきます。
- 他のJOINとは異なり、通常は結合の条件を指定しません。
- 例えば、「商品マスタ」と「色マスタ」を組み合わせて、考えられるすべての商品バリエーションのリストを作成する、といった特殊なケースで利用されます。
サンプルコード
データベースに保存されている複数のテーブルから、関連する情報をまとめて取得したい場合に「JOIN(結合)」という機能を使います。
ここでは、students(生徒)テーブルとclasses(クラス)テーブルを例に、様々なJOINの種類を解説します。
sql/chapter09/01.sql
INNER JOINは、2つのテーブルを結合する際に、指定した条件に一致するデータだけを取得する方法です。 今回の例では、「生徒の所属クラスID」と「クラスのID」が一致する組み合わせ、つまりクラスに所属している生徒の情報だけが表示されます。 クラスに所属していない生徒や、生徒が一人もいないクラスの情報は、結果に含まれません。
1-- INNER JOIN(インナージョイン / 内部結合) 2-- 条件に一致する 生徒だけ を表示(クラスが NULL の生徒は表示されない) 3SELECT 4 students.last_name, 5 students.first_name, 6 classes.name AS class_name 7FROM 8 students 9 INNER JOIN classes ON students.class_id = classes.id;
sql/chapter09/02.sql
LEFT OUTER JOINは、FROM句で最初に指定したテーブル(左側)のデータをすべて取得し、それに結合条件が一致する右側のテーブルのデータを付け加える方法です。
この例では、左側のstudentsテーブルが基準となるため、全ての生徒が表示されます。
もし生徒がクラスに所属していない場合、対応するclassesテーブルのデータは存在しないため、class_nameはNULL(空の値)として表示されます。
1-- LEFT OUTER JOIN(左優先)左外部結合 2-- 生徒は 全員表示。クラスに所属していない生徒の class_name は NULL 3SELECT 4 students.last_name, 5 students.first_name, 6 classes.name AS class_name 7FROM 8 students 9 LEFT OUTER JOIN classes ON students.class_id = classes.id;
sql/chapter09/03.sql
RIGHT OUTER JOINは、LEFT OUTER JOINとは逆に、JOIN句で後に指定したテーブル(右側)のデータをすべて取得する方法です。
この例では、右側のclassesテーブルが基準となるため、全てのクラスが表示されます。
もし、あるクラスに生徒が一人も所属していなくても、そのクラス名は結果に含まれます。その場合、対応する生徒の情報(last_nameやfirst_name)はNULLとして表示されます。
1-- RIGHT OUTER JOIN(右優先) 右外部結合 2-- クラスは 全て表示。生徒がいないクラスでも last_name などは NULL 3SELECT 4 students.last_name, 5 students.first_name, 6 classes.name AS class_name 7FROM 8 students 9 RIGHT OUTER JOIN classes ON students.class_id = classes.id;
sql/chapter09/04.sql
FULL OUTER JOINは、両方のテーブルのデータをすべて取得する方法です。LEFT OUTER JOINとRIGHT OUTER JOINを組み合わせた動きをします。
これにより、クラスに所属していない生徒も、生徒が一人もいないクラスも、すべての情報が結果に含まれます。対応するデータが存在しない部分はNULLとなります。
ただし、MySQLなどの一部のデータベースではこの構文を直接サポートしていません。その場合は、LEFT JOINの結果とRIGHT JOINの結果をUNIONでつなぎ合わせることで、同じ結果を得ることができます。
1-- FULL OUTER JOIN(両方すべて)外部結合 2SELECT 3 students.last_name, 4 students.first_name, 5 classes.name AS class_name 6FROM 7 students 8 FULL OUTER JOIN classes ON students.class_id = classes.id; 9 10-- MySQLは対応していません(他のDBでは可) 11-- 代わりに UNION を使って表現します。 12SELECT 13 students.last_name, 14 students.first_name, 15 classes.name AS class_name 16FROM 17 students 18 LEFT OUTER JOIN classes ON students.class_id = classes.id 19UNION 20SELECT 21 students.last_name, 22 students.first_name, 23 classes.name AS class_name 24FROM 25 students 26 RIGHT OUTER JOIN classes ON students.class_id = classes.id;
sql/chapter09/05.sql
CROSS JOINは、2つのテーブルのすべてのレコードの組み合わせを、条件なしにすべて作成する方法です。
この例では、studentsテーブルの各生徒に対して、classesテーブルのすべてのクラスが1つずつ組み合わされて表示されます。
結果の行数は「生徒の数 × クラスの数」となり、非常に多くのデータが生成される可能性があるため、使用する際は注意が必要です。
1-- CROSS JOIN(全組み合わせ) 2-- 生徒 × クラスの すべての組み合わせを表示 3SELECT 4 students.last_name, 5 students.first_name, 6 classes.name AS class_name 7FROM 8 students 9 CROSS JOIN classes;
おわりに
今回は、複数のテーブルから関連データを取り出すためのJOIN句について学びました。両方のテーブルに共通するデータのみを取得するINNER JOINや、片方のテーブルの全データを取得するLEFT JOINなど、目的に応じて適切な種類を使い分けることが重要です。正しい結果を得るためには、ON句でテーブル同士を結びつける条件を正確に指定することを忘れないようにしましょう。