inner joinで条件を設定しない時
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
-- 注文履歴と商品テーブルと顧客テーブルを結合
select * from order_history o inner join products p on o.product_id = p.id
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
select * from order_history o inner join products p inner join customers c;
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書こうとすると間違ったりするので注意。
Author And Source
この問題について(inner joinで条件を設定しない時), 我々は、より多くの情報をここで見つけました https://qiita.com/risaitou4329/items/47a433915bac4ee70889著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .