MySQL の JOIN(結合)
ここでは MySQL の JOIN(結合)についてご説明します。
サンプルデータベースのテーブルを使いますので、実際にスクリプトを実行してみたい方は、こちら のスクリプトを実行して school_db データベースを作成しておいてください。
JOIN (結合)の基本と種類について
MySQL で複数のテーブルからデータを取得したい時に必要になってくるのが、JOIN (結合)です。
後ほど、ひとつひとつ詳しくサンプルと共に見ていきますが、ここで JOIN の種類と違いをご紹介します。
MySQL の JOIN のタイプには次のようなものがあります。
INNER JOIN (内部結合)
ON で指定した条件が、結合する両方のテーブルにマッチするレコードのみを返します。
LEFT (OUTER) JOIN (左外部結合)
結合の左側のテーブルの全レコードと、ON で指定した条件がマッチする右側のレコードのみを返します。
RIGHT (OUTER) JOIN (右外部結合)
結合の右側のテーブルの全レコードと、ON で指定した条件がマッチする左側のレコードのみを返します。
CROSS JOIN (クロス結合)
CROSS JOIN は他の 3 つの JOIN と少し違って、ON で条件を指定せず、左右両方のテーブルの全てのコンビネーションの行を返します。
結果で得られるレコード数は [ 左のテーブルのレコード数 ] x [ 右のテーブルのレコード数 ] になります。
INNER JOIN (内部結合)を使ってデータを取得する
INNER JOIN を使ってテーブルを結合すると、ON で指定した条件が両方のテーブルでマッチするレコードのみが取得されます。
それでは、INNER JOIN (内部結合)を使ってデータを取得してみましょう。
次のような exam_results テーブルと student テーブルがあります。
student_id がマッチするという条件で INNER JOIN することによって、exam_results テーブルの exam_id = 2 で student_id が students テーブルに存在するレコードの student の名前をこのように取得することができます。
SELECT er.*,
s.first_name,
s.last_name
FROM exam_results AS er
INNER JOIN students AS s
ON er.student_id = s.student_id
WHERE er.exam_id = 2;
[実行結果]
以下のように、exam_results テーブルと student テーブルの両方のテーブルに student_id が存在している、student_id が 1, 3, 4 のレコードのみが取得されています。
LEFT (OUTER) JOIN (左外部結合)を使ってデータを取得する
LEFT JOIN を使ってテーブルを結合すると、結合の左側のテーブルの全レコードと、ON で指定した条件がマッチする右側のレコードのみが取得できるます。
それでは、LEFT JOIN を使ってデータを取得してみましょう。
先ほどの exam_results テーブルと student テーブル から、student_id がマッチするという条件で LEFT JOIN することによって、exam_results テーブルの exam_id = 2 の全レコードと、student_id がマッチする student の名前が取得できます。
SELECT er.*,
s.first_name,
s.last_name
FROM exam_results AS er
LEFT JOIN students AS s
ON er.student_id = s.student_id
WHERE er.exam_id = 2;
[実行結果]
以下のように、exam_results テーブルの exam_id = 2 の全レコード(4 レコード)に、 student_id がマッチする student_id が 1, 3, 4 の名前のみが students テーブルから取得されています。
LEFT JOIN を使う時に少し注意しないといけないのは、WHERE 句で右テーブルのカラムを使って条件を指定してしまうと、左テーブルのマッチしない行は結果セットに含まれません。
INNER JOIN と同じ結果になります。
SELECT er.*,
s.first_name,
s.last_name
FROM exam_results AS er
LEFT JOIN students AS s
ON er.student_id = s.student_id
WHERE er.exam_id = 2
AND s.gender = 'M';
[実行結果]
これで、意図したデータが取得できるのであれば、パフォーマンスの点でも、わかりやすさの点でも INNER JOIN を使ったほうがよいと思います。
もし、exam_results テーブルの exam_id = 2 の全データと男性の学生の名前のみを取得したい場合は、s.gender = 'M' の条件を ON にもってくることで取得できます。
SELECT er.*,
s.first_name,
s.last_name
FROM exam_results AS er
LEFT JOIN students AS s
ON er.student_id = s.student_id
AND s.gender = 'M'
WHERE er.exam_id = 2;
[実行結果]
RIGHT (OUTER) JOIN (右外部結合)を使ってデータを取得する
RIGHT JOIN を使ってテーブルを結合すると、結合の右側のテーブルの全レコードと、ON で指定した条件がマッチする左側のレコードのみが取得できます。
LEFT JOIN の反対です。
例えば、先ほどの LEFT JOIN のクエリーの LEFT JOIN を RIGHT JOIN に置き換えて、左右のテーブルを入れ替えると、全く同じ結果が得られます。
SELECT er.*,
s.first_name,
s.last_name
FROM students AS s
RIGHT JOIN exam_results AS er
ON s.student_id = er.student_id
WHERE er.exam_id = 2;
[実行結果]
RIGHT JOIN を使って、exam_results テーブルの exam_id = 2 の全レコードと、student_id がマッチする student の名前が取得できていますね。
CROSS JOIN (クロス結合)を使ってデータを取得する
CROSS JOIN (クロス結合) では、INNER・LEFT・RIGHT JOIN と違って、ON でマッチの条件を指定しません。
[左テーブル] CROSS JOIN [右テーブル] のように結合すると、[左テーブル] と [右テーブル]の両方のテーブルの、全てのコンビネーションの行の結果セットを取得することができます。
ですので、結果で得られるレコード数は [ 左のテーブルのレコード数 ] x [ 右のテーブルのレコード数 ] になります。
それでは、CROSS JOIN を使ってデータを取得してみましょう。
次のような students テーブルと exams テーブルがあります。
CROSS JOIN を使って、students テーブルと exams テーブルを結合すると次のようになります。
SELECT *
FROM students
CROSS JOIN exams;
[実行結果]
students テーブルの行数 6 * exams テーブルの行数 3 = 18 レコードで、全てのコンビネーションの行の結果セットが取得できました。
このように各生徒に対して、各テストの一覧表を作りたいような時に便利です。
最後に、JOIN とだけ書くと ON がある場合は INNER JOIN に、NO がない場合は CROSS JOIN になります。
以上、MySQL の JOIN(結合)についてご説明しました。