どうも、hosigakiです!
今日は、2つのテーブルを結合する際の、結合条件について、詳しく解説します!
結合条件の書き方は3パターン!
テーブル結合には、三通りのパターンが存在します。
ここでは、以下二つのテーブルを結合する例を元に、解説します。
user_id | user_name | user_created_date |
---|---|---|
1 | 太郎 | 2023-1-1 |
2 | 次郎 | 2023-1-2 |
3 | 三郎 | 2023-1-3 |
4 | 四郎 | 2023-1-4 |
user_id | item_name | purchase_created_date |
---|---|---|
1 | 干し柿詰め合わせ | 2023-1-5 |
2 | 干し柿せんべい | 2023-1-6 |
3 | 干し柿ジュース | 2023-1-7 |
パターン① 両方のテーブルのカラムの条件だけ書く
「結合条件」と聞くと、多くの方が以下のような書き方をイメージするのではないでしょうか。
SELECT
*
FROM
users
LEFT OUTER JOIN purchases
ON users.user_id = purchases.user_id
上記はテーブル結合時、「どのカラムをどのカラムに紐づけるのか」を指定したものになります。よくSQLの教本などに載っている書き方ですね!
実行結果は以下となります。
user_id | user_name | user_created_date | user_id | item_name | purchase_created_date |
---|---|---|---|---|---|
1 | 太郎 | 2023-1-1 | 1 | 干し柿詰め合わせ | 2023-1-5 |
2 | 次郎 | 2023-1-2 | 2 | 干し柿せんべい | 2023-1-6 |
3 | 三郎 | 2023-1-3 | 3 | 干し柿ジュース | 2023-1-7 |
4 | 四郎 | 2023-1-4 |
パターン② 片方のテーブルのカラムの条件だけ書く
ここからが今日の本題です。
実は、テーブルの結合条件内には、片方のテーブルのカラムの条件のみ書くという方法があるんです!
SELECT
*
FROM
users
LEFT OUTER JOIN purchases
ON users.user_created_date >= "2023-1-3"
実行結果は以下になります。
user_id | user_name | user_created_date | user_id | item_name | purchase_created_date |
---|---|---|---|---|---|
1 | 太郎 | 2023-1-1 | |||
2 | 次郎 | 2023-1-2 | |||
3 | 三郎 | 2023-1-3 | 1 | 干し柿詰め合わせ | 2023-1-5 |
3 | 三郎 | 2023-1-3 | 2 | 干し柿せんべい | 2023-1-6 |
3 | 三郎 | 2023-1-3 | 3 | 干し柿ジュース | 2023-1-7 |
4 | 四郎 | 2023-1-4 | 1 | 干し柿詰め合わせ | 2023-1-5 |
4 | 四郎 | 2023-1-4 | 2 | 干し柿せんべい | 2023-1-6 |
4 | 四郎 | 2023-1-4 | 3 | 干し柿ジュース | 2023-1-7 |
ここで注目したいのは、以下二点です。
- users.user_created_dateが2023-1-2以前のレコードには、purchasesテーブルのレコードが結合されていない
- users.user_created_dateが2023-1-3以降のレコードには、purchasesテーブルのすべてのレコードが結合されている
このことから、次のように言うことができますね!
テーブルA・Bの結合時、テーブルAの条件のみ書いた場合
テーブルAの条件に合致しないレコード → テーブルBのレコードは紐づかない
テーブルAの条件に合致するレコード → テーブルBのレコードがすべて紐づく
ちなみに、usersテーブルの条件ではなく、purchasesテーブルの条件のみ記載した場合も、上記と同じことが言えます!
SELECT
*
FROM
users
LEFT OUTER JOIN purchases
ON purchases.purchase_created_date >= "2023-1-6"
user_id | user_name | user_created_date | user_id | item_name | purchase_created_date |
---|---|---|---|---|---|
1 | 太郎 | 2023-1-1 | 2 | 干し柿せんべい | 2023-1-6 |
1 | 太郎 | 2023-1-1 | 3 | 干し柿ジュース | 2023-1-7 |
2 | 次郎 | 2023-1-2 | 2 | 干し柿せんべい | 2023-1-6 |
2 | 次郎 | 2023-1-2 | 3 | 干し柿ジュース | 2023-1-7 |
3 | 三郎 | 2023-1-3 | 2 | 干し柿せんべい | 2023-1-6 |
3 | 三郎 | 2023-1-3 | 3 | 干し柿ジュース | 2023-1-7 |
4 | 四郎 | 2023-1-4 | 2 | 干し柿せんべい | 2023-1-6 |
4 | 四郎 | 2023-1-4 | 3 | 干し柿ジュース | 2023-1-7 |
上記では、purchasesテーブルのレコードの条件だけを定めたので、以下のような抽出結果となっています。
- purchases.purchase_created_date が 2023-1-5以前のレコードには、usersテーブルのレコードが結合されていない
- purchases.purchase_created_date が 2023-1-6以降のレコードには、usersテーブルのレコードがすべて結合されている
なお、今回は左部外部結合(LEFT OUTER JOIN)を行っているため、usersテーブルのレコードが紐づかなかったpurchasesテーブル側のレコードは、抽出結果から除外されています。
パターン③ 上記二つの合わせ技
パターン③は、パターン①・②の合わせ技になります。
以下、クエリと抽出結果です。
SELECT
*
FROM
users
LEFT OUTER JOIN purchases
ON users.user_id = purchases.user_id /*パターン1の条件*/
AND users.user_created_date >= "2023-1-3" /*パターン2の条件*/
user_id | user_name | user_created_date | user_id | item_name | purchase_created_date |
---|---|---|---|---|---|
1 | 太郎 | 2023-1-1 | |||
2 | 次郎 | 2023-1-2 | |||
3 | 三郎 | 2023-1-3 | 3 | 干し柿ジュース | 2023-1-7 |
4 | 四郎 | 2023-1-4 |
以下にパターン①の抽出結果を再掲しますので、上下それぞれ見比べてみましょう!
user_id | user_name | user_created_date | user_id | item_name | purchase_created_date |
---|---|---|---|---|---|
1 | 太郎 | 2023-1-1 | 1 | 干し柿詰め合わせ | 2023-1-5 |
2 | 次郎 | 2023-1-2 | 2 | 干し柿せんべい | 2023-1-6 |
3 | 三郎 | 2023-1-3 | 3 | 干し柿ジュース | 2023-1-7 |
4 | 四郎 | 2023-1-4 |
パターン③の方は、ON句に条件が追加されたことで、users.user_created_dateが2023-1-2以前のレコードに対しては、purchasesテーブルのレコードが紐づいていないことが分かりますね!
(補足として...)
上記では左部外部結合(LEFT OUTER JOIN)時の例を紹介してきました。
仮に内部結合(INNER JOIN)で抽出した場合であっても、上記抽出結果で空白行がただ除外されるだけなので、ご安心ください!
今回は、テーブル結合のパターンについてご紹介しました。
特にパターン③については、知っておくといざというときに便利なので、ぜひ覚えておきましょう!
最後まで読んでいただきありがとうございました!
また次の記事でお会いしましょう(^^)/