テーブルって結合すると便利ですよね。
結合しないと得たいものを得ることができないことがよくあります。
しかし、右にJOINする?左?いや、INNER?
ってなる
結果、副問い合わせをする。
パフォーマンス的にどうなの?ってなる。
ということで、今日の目標は
JOIN使いこなせるようになろう!
<データ>
# SELECT * FROM parent_table ORDER BY id;
id | name
—-+——–
1 | サザエ
2 | フネ
3 | タイ子
# SELECT * FROM child_table ORDER BY id;
id | name | parent_id
—-+——–+———–
1 | サザエ | 2
2 | カツオ | 2
3 | ワカメ | 2
4 | タラ | 1
5 | イクラ | 3
6 | タマ |
まずは、INNER JOIN
・child_tableにINNNER JOINするパターン
# SELECT * FROM child_table INNER JOIN parent_table ON child_table.parent_id = parent_table.id ORDER BY child_table.id;
id | name | parent_id | id | name
—-+——–+———–+—-+——–
1 | サザエ | 2 | 2 | フネ
2 | カツオ | 2 | 2 | フネ
3 | ワカメ | 2 | 2 | フネ
4 | タラ | 1 | 1 | サザエ
5 | イクラ | 3 | 3 | タイ子
タマはparent_idがないため、結合されませんでした。
・parent_tableにINNNER JOINするパターン
# SELECT * FROM parent_table INNER JOIN child_table ON parent_table.id =child_table. parent_id ORDER BY child_table.id;
id | name | id | name | parent_id
—-+———-+—-+———–+———–
2 | フネ | 1 | サザエ | 2
2 | フネ | 2 | カツオ | 2
2 | フネ | 3 | ワカメ | 2
1 | サザエ | 4 | タラ | 1
3 | タイ子 | 5 | イクラ | 3
ここでも、タマはparent_idがないため、結合されませんでした。
よって、左右テーブルどちらにINNER JOINしてもデータの内容としては変わらない。
また、フネ(parent_id=2)に関しては、3行あります。
▶︎INNER JOINは、
左右それぞれのテーブル.カラムの値が一致するレコードだけを取得する。
よって、一致しないレコードは削除される。
次はOUTER JOIN。
まずは、parent_tableにOUTER JOIN
parent_tableが右に来るのでRIGHT JOINしてます。
# SELECT * FROM child_table RIGHT JOIN parent_table ON child_table.parent_id = parent_table.id ORDER BY child_table.id;
id | name | parent_id | id | name
—-+——–+———–+—-+——–
1 | サザエ | 2 | 2 | フネ
2 | カツオ | 2 | 2 | フネ
3 | ワカメ | 2 | 2 | フネ
4 | タラ | 1 | 1 | サザエ
5 | イクラ | 3 | 3 | タイ子
右のparent_tableを基本として結合するため、タマのように結合条件のparetn_table.idを持たないchild_table.parent_idは結合されませんでした。
次に、child_tableにOUTER JOIN
child_tableが左に来るのでLEFT JOINしてます。
# SELECT * FROM child_table LEFT JOIN parent_table ON child_table.parent_id = parent_table.id ORDER BY child_table.id;
id | name | parent_id | id | name
—-+——–+———–+—-+——–
1 | サザエ | 2 | 2 | フネ
2 | カツオ | 2 | 2 | フネ
3 | ワカメ | 2 | 2 | フネ
4 | タラ | 1 | 1 | サザエ
5 | イクラ | 3 | 3 | タイ子
6 | タマ | | |
左のchild_tableを基本として結合するため、タマのように結合条件のchild_table.parent_idがparent_table.idに存在しなくてもNULLとして結合してくれる。
▶︎OUTER JOINは、
基本となったテーブル(左右どちらか)のレコードは全て取得し、左右それぞれのテーブル.カラムの値が一致しないレコードもNULLとして結合する。
※FULL JOINについて
ここで、データを追加する。
# INSERT INTO parent_table VALUES (4, ‘花澤さん’);
# SELECT * FROM parent_table ORDER BY id;
id | name
—-+———-
1 | サザエ
2 | フネ
3 | タイ子
4 | 花澤さん
# SELECT * FROM child_table ORDER BY id;
id | name | parent_id
—-+——–+———–
1 | サザエ | 2
2 | カツオ | 2
3 | ワカメ | 2
4 | タラ | 1
5 | イクラ | 3
6 | タマ |
おわかりの通り、花澤さんにひもづくchild_table.parent_idはない。
また、先ほどに続いてタマにひもづくparent_table.idもない。
>parent_table(右)に結合!
# SELECT * FROM child_table RIGHT JOIN parent_table ON child_table.parent_id = parent_table.id ORDER BY child_table.id;
id | name | parent_id | id | name
—-+——–+———–+—-+———-
1 | サザエ | 2 | 2 | フネ
2 | カツオ | 2 | 2 | フネ
3 | ワカメ | 2 | 2 | フネ
4 | タラ | 1 | 1 | サザエ
5 | イクラ | 3 | 3 | タイ子
| | | 4 | 花澤さん
child_tableのタマのレコードはないが、
parent_tableは全て取得されている。
>child_table(左)に結合!
# SELECT * FROM child_table LEFT JOIN parent_table ON child_table.parent_id = parent_table.id ORDER BY child_table.id;
id | name | parent_id | id | name
—-+——–+———–+—-+——–
1 | サザエ | 2 | 2 | フネ
2 | カツオ | 2 | 2 | フネ
3 | ワカメ | 2 | 2 | フネ
4 | タラ | 1 | 1 | サザエ
5 | イクラ | 3 | 3 | タイ子
6 | タマ | | |
parent_tableの花澤さんのレコードはないが、
child_tableは全て取得されている。
>>本題のFULL JOIN
# SELECT * FROM child_table FULL JOIN parent_table ON child_table.parent_id = parent_table.id ORDER BY child_table.id;
id | name | parent_id | id | name
—-+——–+———–+—-+———-
1 | サザエ | 2 | 2 | フネ
2 | カツオ | 2 | 2 | フネ
3 | ワカメ | 2 | 2 | フネ
4 | タラ | 1 | 1 | サザエ
5 | イクラ | 3 | 3 | タイ子
6 | タマ | | |
| | | 4 | 花澤さん
# SELECT * FROM parent_table FULL JOIN child_table ON child_table.parent_id = parent_table.id ORDER BY child_table.id;
id | name | id | name | parent_id
—-+———-+—-+——–+———–
2 | フネ | 1 | サザエ | 2
2 | フネ | 2 | カツオ | 2
2 | フネ | 3 | ワカメ | 2
1 | サザエ | 4 | タラ | 1
3 | タイ子 | 5 | イクラ | 3
| | 6 | タマ |
4 | 花澤さん | | |
左右どちらにJOINするにしても、左右全てのレコードを取得する。