SQLはテーブル結合の方法がありすぎて、マジわかりませんよね。 例えばPostgreSQLの場合...
- https://www.postgresql.jp/document/15/html/queries-union.html
- https://www.postgresql.jp/document/15/html/tutorial-join.html
本を読んだりマニュアルを読んだりしましたが、わかったようなわからないような、そんなもやもやした感じで日々過ごしています。
売上合計してみる
毎回やるたびに忘れるので、よくやるやつをまとめておこうと思いました。 今回の場合、こんなテーブルがそれぞれあったとして、テーブルを縦につなげて、3つのテーブルを要するに30行のデータにして、amount_sold列のデータの合計を求めてみます。
testdb=# SELECT * FROM uriage2301; number | name | okashi | amount_sold --------+-------+-----------+------------- 1 | Alice | candy | 100 2 | Alice | candy | 50 3 | Alice | cookie | 150 4 | Bob | chocolate | 200 5 | Bob | chocolate | 300 6 | Jane | cookie | 150 7 | Alice | chocolate | 180 8 | Bob | chocolate | 180 9 | Bob | chocolate | 180 10 | Jane | cookie | 220 (10 行) testdb=# SELECT * FROM uriage2302; number | name | okashi | amount_sold --------+------+-----------+------------- 1 | Jane | chocolate | 120 2 | Bob | chocolate | 120 3 | Ted | cookie | 120 4 | Bob | chocolate | 120 5 | Bob | chocolate | 120 6 | Ted | cookie | 120 7 | Jane | chocolate | 180 8 | Jane | chocolate | 180 9 | Bob | cookie | 120 10 | Bob | cookie | 120 (10 行) testdb=# SELECT * FROM uriage2303; number | name | okashi | amount_sold --------+-------+-----------+------------- 1 | Bob | candy | 120 2 | Ted | chocolate | 180 3 | Jane | candy | 120 4 | Alice | chocolate | 120 5 | Bob | chocolate | 120 6 | Bob | cookie | 120 7 | Jane | chocolate | 280 8 | Ted | chocolate | 240 9 | Bob | cookie | 180 10 | Bob | chocolate | 100 (10 行)
少なければそれぞれ合計を出して計算すれば良いですよね。
testdb=# SELECT sum(amount_sold) FROM uriage2301; sum ------ 1710 (1 行) testdb=# SELECT sum(amount_sold) FROM uriage2302; sum ------ 1320 (1 行) testdb=# SELECT sum(amount_sold) FROM uriage2303; sum ------ 1580 (1 行)
これをあえて面倒くさい方法で求めてみます。
UNION ALLでテーブルをつなげる
テーブルは全く列のデータが同じ場合、UNION ALLを使って結合できます。 こんな感じです。
SELECT * FROM uriage2301 UNION ALL SELECT * FROM uriage2302 UNION ALL SELECT * FROM uriage2303 ORDER BY 1;
結果はこうなります。思ったとおりです。ORDER BY 1
のお陰で良い感じに番号順に並んでくれています。
最初、UNION
を使っていて行数が合わなくて少し悩みました。
今回の例はデータ集計なので重複の除外はしてはいけません。というわけでUNION ALL
を使うのが適切です。
number | name | okashi | amount_sold --------+-------+-----------+------------- 1 | Alice | candy | 100 1 | Bob | candy | 120 1 | Jane | chocolate | 120 2 | Bob | chocolate | 120 2 | Ted | chocolate | 180 2 | Alice | candy | 50 3 | Jane | candy | 120 3 | Alice | cookie | 150 3 | Ted | cookie | 120 4 | Alice | chocolate | 120 4 | Bob | chocolate | 200 4 | Bob | chocolate | 120 5 | Bob | chocolate | 300 5 | Bob | chocolate | 120 5 | Bob | chocolate | 120 6 | Ted | cookie | 120 6 | Jane | cookie | 150 6 | Bob | cookie | 120 7 | Alice | chocolate | 180 7 | Jane | chocolate | 280 7 | Jane | chocolate | 180 8 | Jane | chocolate | 180 8 | Bob | chocolate | 180 8 | Ted | chocolate | 240 9 | Bob | cookie | 120 9 | Bob | chocolate | 180 9 | Bob | cookie | 180 10 | Jane | cookie | 220 10 | Bob | chocolate | 100 10 | Bob | cookie | 120
それぞれのテーブルで小計してみる
それぞれのテーブルのamount_soldを計算する場合はこんな感じ。
SELECT sum(amount_sold) FROM uriage2301 UNION ALL SELECT sum(amount_sold) FROM uriage2302 UNION ALL SELECT sum(amount_sold) FROM uriage2303 ORDER BY 1; sum ------ 1320 1580 1710 (3 行)
3つのテーブルのamount_soldを合計してみる
じゃあこれを合計するには? こんな感じです。サブクエリーを使っています。
SELECT sum(amount_sold) FROM ( SELECT * FROM uriage2301 UNION ALL SELECT * FROM uriage2302 UNION ALL SELECT * FROM uriage2303 ) AS t ORDER BY 1; sum ------ 4610 (1 行)
やっていることは簡単なんですが、なかなか難しいです。 しかし、一つずつ覚えていくしかありません。
参考になった情報
この情報が参考になりました。