MySQL – JOIN – INNER/LEFT/RIGHT/FULL OUTER

準備

以下の2つのテーブルを準備する。

students
学生IDと学生名を保存。
courses
学科IDと学科名を保存。

studentsテーブルの作成とデータ登録のクエリー。

実行結果。

coursesテーブルの作成とデータ登録のクエリー。

実行結果。

JOIN~総当たり

FROM句のテーブルに対して単にJOINでテーブルを指定すると、2つのテーブルの全要素の組み合わせが得られる。

実行結果。

結合テーブル

studentsテーブルとcoursesテーブルの結合テーブルを準備する。各学生の履修学科に関するデータ。

クエリーの実行結果、

INNER JOIN

結合テーブルに基づいて、2つのテーブルの両方に存在するデータを取り出す。studentscoursesの積集合に相当する。INNERは書かなくても内部結合になる。

student_coursesテーブルとstudentsテーブルを結合するクエリーの例。結合の結果、studentsテーブルから学生名を得られる。

実行結果。

3つのテーブルの場合、JOIN ... ON句を並べればよい。以下の例ではcoursesテーブルも結合して、学科名も得ている。

実行結果。student_coursesテーブルは学生IDと学科IDしか持っていないが、studentsテーブル、coursesテーブルと結合することで学生名と学科名を使えるようになる。

LEFT OUTER JOIN

LEFT OUTER JOINは、先に指定されたテーブル(左テーブル)の全レコードに対して、JOINで指定したレコードを対応させる。左テーブルに対応するレコードがないときはNULLになる。LEFT JOINと書いても同じ。

以下のクエリーは、studentsの全学生データに対してstudent_coursesの履修科目データを左結合させる。studentsには登録されているがstudent_coursesにない学生(学科を履修していない学生)についてはNULLになる。

実行結果は以下の通りで、学生IDの伊藤君はstudent_coursesテーブルに存在しないので、course_idNULLになっている。

学科名も欲しい場合は、coursesテーブルを左結合させる。

実行結果。学科を履修していない伊藤君のデータは、course_nameについてもNULLになる。

RIGHT OUTER JOIN

RIGHT JOINは後から指定されたテーブルの全データに対して、先に指定されたテーブルを結合させる。先に指定されたテーブルに対応するレコードがない場合にはNULLになる。RIGHT JOINと書いても同じ。

以下は、student_coursesテーブルのデータにcoursesテーブルのデータを右結合させている。どの学生にも履修されていない学科がある場合はNULLになる。

実行結果。化学はどの学生にも履修されていないのでNULLになっている。

3つ以上のテーブルでは、最も右側のテーブルをRIGHT JOINを連ねる。最後以外のJOINRIGHTがなくても同じ結果になる。

実行結果。履修されていない化学の学生IDと学生名がNULLになっている。

RIGHT JOINのテーブルを入れ替えることで、LEFT JOINで同じ結果を得られる。履修科目に関する上の例をLEFT JOINで書きなおすと以下の通り。

実行結果は同じ。

FULL OUTER JOIN

FULL OUTER JOINは指定されたテーブルの全データを含める。いずれかのデータが存在しない場合はNULLとなる。テーブルのデータ群の和集合に相当する。

MySQLにはFULL JOINが定義されていないので、同等の機能はUNIONで実現する。

  • 2つのテーブルの場合にはLEFT JOINRIGHT JOINの結果をUNION
  • 結合テーブルがある場合には、それぞれのLEFT JOINの結果をUNION
  • UNIONの際に、各SELECTのカラムを同じにしておく

以下は、studentscoursesに対するstudent_coursesLEFT JOINの結果をUNIONで結合している。科目を履修していない学生は学科がNULLとなり、履修されていない科目が学生がNULLとなる。

実行結果。学科を履修していない伊藤君の学科欄はNULLになり、だれにも履修されていない化学は学生欄がNULLになっている。

カラム名の指定によって結果が違う

LEFT OUTER JOINのところで、学生IDと学科IDをstudents.idcouses.idのようにそれぞれのテーブルから指定していた。

一方で、同じIDをstudent_courseのstudent_idcouse_idで指定することもできる。こちらで指定すれば、識別のためのエイリアスを定義しなくていいので便利そうだ。

しかしこれらを使うと、OUTER JOINの際に存在しないIDとして扱われてNULLになってしまう。

上のクエリーを実行した結果が以下で、化学を履修している学生がいないので、student_coursesに該当するデータがなく、student_idcourse_idNULLになっている。

これらを表示させたいときには、LEFT OUTER JOINの例のように、左結合される側(全データが使われる側)のテーブルでカラムを指定するとよい。

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です