MySQL の JOIN(結合)

ここでは MySQL の JOIN(結合)についてご説明します。

サンプルデータベースのテーブルを使いますので、実際にスクリプトを実行してみたい方は、こちら のスクリプトを実行して school_db データベースを作成しておいてください。

JOIN (結合)の基本と種類について

MySQL で複数のテーブルからデータを取得したい時に必要になってくるのが、JOIN (結合)です。

後ほど、ひとつひとつ詳しくサンプルと共に見ていきますが、ここで JOIN の種類と違いをご紹介します。


MySQL の JOIN のタイプには次のようなものがあります。

INNER JOIN (内部結合)

ON で指定した条件が、結合する両方のテーブルにマッチするレコードのみを返します。

MySQL の JOIN(結合)1


LEFT (OUTER) JOIN (左外部結合)

結合の左側のテーブルの全レコードと、ON で指定した条件がマッチする右側のレコードのみを返します。

MySQL の JOIN(結合)2


RIGHT (OUTER) JOIN (右外部結合)

結合の右側のテーブルの全レコードと、ON で指定した条件がマッチする左側のレコードのみを返します。

MySQL の JOIN(結合)3


CROSS JOIN (クロス結合)

CROSS JOIN は他の 3 つの JOIN と少し違って、ON で条件を指定せず、左右両方のテーブルの全てのコンビネーションの行を返します。

結果で得られるレコード数は [ 左のテーブルのレコード数 ] x [ 右のテーブルのレコード数 ] になります。

MySQL の JOIN(結合)4


INNER JOIN (内部結合)を使ってデータを取得する

INNER JOIN を使ってテーブルを結合すると、ON で指定した条件が両方のテーブルでマッチするレコードのみが取得されます。

MySQL の JOIN(結合)1

それでは、INNER JOIN (内部結合)を使ってデータを取得してみましょう。


次のような exam_results テーブルと student テーブルがあります。

MySQL の JOIN(結合)5

MySQL の JOIN(結合)6


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;

[実行結果]

MySQL の JOIN(結合)7

以下のように、exam_results テーブルと student テーブルの両方のテーブルに student_id が存在している、student_id が 1, 3, 4 のレコードのみが取得されています。

MySQL の JOIN(結合)8

LEFT (OUTER) JOIN (左外部結合)を使ってデータを取得する

LEFT JOIN を使ってテーブルを結合すると、結合の左側のテーブルの全レコードと、ON で指定した条件がマッチする右側のレコードのみが取得できるます。

MySQL の JOIN(結合)2

それでは、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;

[実行結果]

MySQL の JOIN(結合)9

以下のように、exam_results テーブルの exam_id = 2 の全レコード(4 レコード)に、 student_id がマッチする student_id が 1, 3, 4 の名前のみが students テーブルから取得されています。

MySQL の JOIN(結合)10


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'; 

[実行結果]

MySQL の JOIN(結合)11


これで、意図したデータが取得できるのであれば、パフォーマンスの点でも、わかりやすさの点でも 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;

[実行結果]

MySQL の JOIN(結合)12

RIGHT (OUTER) JOIN (右外部結合)を使ってデータを取得する

RIGHT JOIN を使ってテーブルを結合すると、結合の右側のテーブルの全レコードと、ON で指定した条件がマッチする左側のレコードのみが取得できます。

MySQL の JOIN(結合)3

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;

[実行結果]

MySQL の JOIN(結合)13

RIGHT JOIN を使って、exam_results テーブルの exam_id = 2 の全レコードと、student_id がマッチする student の名前が取得できていますね。


CROSS JOIN (クロス結合)を使ってデータを取得する

CROSS JOIN (クロス結合) では、INNER・LEFT・RIGHT JOIN と違って、ON でマッチの条件を指定しません。

[左テーブル] CROSS JOIN [右テーブル] のように結合すると、[左テーブル] と [右テーブル]の両方のテーブルの、全てのコンビネーションの行の結果セットを取得することができます。

ですので、結果で得られるレコード数は [ 左のテーブルのレコード数 ] x [ 右のテーブルのレコード数 ] になります。

MySQL の JOIN(結合)4


それでは、CROSS JOIN を使ってデータを取得してみましょう。

次のような students テーブルと exams テーブルがあります。

MySQL の JOIN(結合)6

MySQL の JOIN(結合)15


CROSS JOIN を使って、students テーブルと exams テーブルを結合すると次のようになります。

SELECT 	*
FROM 	students
			CROSS JOIN exams;

[実行結果]

MySQL の JOIN(結合)16

students テーブルの行数 6 * exams テーブルの行数 3 = 18 レコードで、全てのコンビネーションの行の結果セットが取得できました。

このように各生徒に対して、各テストの一覧表を作りたいような時に便利です。


最後に、JOIN とだけ書くと ON がある場合は INNER JOIN に、NO がない場合は CROSS JOIN になります。

以上、MySQL の JOIN(結合)についてご説明しました。

© 2024 MySQL 入門