9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

inner joinで条件を設定しない時

Posted at

inner join で条件を指定しないとどうなるか

inner join句は結合するテーブル同士でどのキーで結合するかを指定する。
指定しなくてもクエリは実行される(実行エラーにならない)が、挙動が変わる。

テスト用テーブル

customers (顧客テーブル)

id customer_name
1 hirata
2 kanazawa
3 fukuda

products (商品テーブル 名称と金額のみ)

id product_name price
1 pencil 100
2 eraser 120
3 note 150

order_history (注文履歴、注文数などは省略)

id customer_id product_id date
1 1 1 2021-06-07
2 2 1 2021-06-07
3 2 2 2021-06-07
4 2 3 2021-06-08
5 3 1 2021-06-05
6 3 3 2021-06-08

基本的な(left) inner join句の書き方

-- 注文履歴と商品テーブルと顧客テーブルを結合
select * from order_history o inner join products p on o.product_id = p.id 

result

o.id o.customer_id o.product_id o.order_date p.id p.product_name p.price c.id c.customer_name
1 1 1 2021-06-07 1 pencil 100 1 hirata
2 2 1 2021-06-07 1 pencil 100 2 kanazawa
3 2 2 2021-06-07 2 eraser 120 2 kanazawa
4 2 3 2021-06-08 3 note 150 2 kanazawa
5 3 1 2021-06-05 1 pencil 100 3 fukuda
6 3 3 2021-06-08 3 note 150 3 fukuda

注文履歴をベースに、

結合条件を指定しない場合

select * from order_history o inner join products p inner join customers c;

result

o.id o.customer_id o.product_id o.order_date p.id p.product_name p.price c.id c.customer_name
1 1 1 2021-06-07 1 pencil 100 1 hirata
1 1 1 2021-06-07 2 eraser 120 1 hirata
1 1 1 2021-06-07 3 note 150 1 hirata
1 1 1 2021-06-07 1 pencil 100 2 kanazawa
1 1 1 2021-06-07 2 eraser 120 2 kanazawa
1 1 1 2021-06-07 3 note 150 2 kanazawa
1 1 1 2021-06-07 1 pencil 100 3 fukuda
1 1 1 2021-06-07 2 eraser 120 3 fukuda
1 1 1 2021-06-07 3 note 150 3 fukuda
2 2 1 2021-06-07 1 pencil 100 1 hirata
2 2 1 2021-06-07 2 eraser 120 1 hirata
2 2 1 2021-06-07 3 note 150 1 hirata
2 2 1 2021-06-07 1 pencil 100 2 kanazawa
2 2 1 2021-06-07 2 eraser 120 2 kanazawa
.......

と、結果が大量になるので途中までだが、結合条件を指定しないと全行で結合してしまう。
これはcross join指定をしているのと同じ。

select * from order_history o cross join products p cross join customers c

この挙動が便利な時(cross join)

全組み合わせが確認できるので、それなりに便利。
私は、日付ごとに集計結果を出力したい時で、「集計結果にならない日付も出力したい場合」に全ての日付でテーブルを作成する時に使用したりします。
例のorder_historyでは、6月5日、7日、8日のデータがあるため、これで商品の日付ごとを集計すると6日のデータが出力されない。

select product_id ,order_date, sum(price) from order_history o inner join products p on p.id = o.product_id group by product_id ,order_date;
product_id order_date sum(price)
1 2021-06-05 100
1 2021-06-07 200
2 2021-06-07 120
3 2021-06-08 300

cross joinで商品✕日付の全組み合わせを出力しておいて、それに結果を紐付けると結果の無い日付も出力対象になる。

select p.id, p.product_name, d, order_date, sum_price from products p cross join
(select
date_format(date_add('2021-06-04', interval td.generate_series day), '%Y-%m-%d') as d
from
(
SELECT 0 generate_series FROM DUAL WHERE (@num:=1-1)*0 UNION ALL
SELECT @num:=@num+1 FROM `information_schema`.COLUMNS LIMIT 7
) as td
) date_table
left join 
(select product_id ,order_date, sum(price) as sum_price from order_history o inner join products p on p.id = o.product_id group by product_id ,order_date) ledger
on ledger.product_id = p.id and ledger.order_date = date_table.d
order by p.id, d
;
id product_name d order_date sum_price
1 pencil 2021-06-05 2021-06-05 100
1 pencil 2021-06-06
1 pencil 2021-06-07 2021-06-07 200
1 pencil 2021-06-08
1 pencil 2021-06-09
1 pencil 2021-06-10
1 pencil 2021-06-11
2 eraser 2021-06-05
2 eraser 2021-06-06
2 eraser 2021-06-07 2021-06-07 120
2 eraser 2021-06-08
2 eraser 2021-06-09
2 eraser 2021-06-10
2 eraser 2021-06-11
3 note 2021-06-05
3 note 2021-06-06
3 note 2021-06-07
3 note 2021-06-08 2021-06-08 300
3 note 2021-06-09
3 note 2021-06-10
3 note 2021-06-11

MySQL8.0はWindow関数も使えたり集計関数も増えているので、5.7までで無理やりやるとこんな感じというところはありますが。
ともあれ、たまにSQL書こうとすると間違ったりするので注意。

9
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?