質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

JOIN

これはSQL文のJOINに関するタグです。リレーショナルデータベースシステムの二つ以上のテーブルを結合する際に、この構文が利用されます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

Q&A

解決済

5回答

4643閲覧

カラムごとに集計し別テーブルに結合する方法で困っています

akasuka

総合スコア21

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

JOIN

これはSQL文のJOINに関するタグです。リレーショナルデータベースシステムの二つ以上のテーブルを結合する際に、この構文が利用されます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

0グッド

0クリップ

投稿2016/08/26 15:33

編集2016/08/26 15:35

mariaDBで集計した結果をjoin?union?する方法がうまくいかず困っています。

テーブルは下記のようなイメージです。

Aテーブル Bテーブル Cテーブル +--+----+ +--+----+ +--+----+ |id|avol| |id|bvol| |id|name| +--+----+ +--+----+ +--+----+ | 1| 1| | 2| 1| | 1|aaaa| | 2| 1| | 2| 1| | 2|bbbb| | 2| 2| | 2| 1| | 3|cccc| | 3| 2| | 3| 1| | 4|dddd| | 3| 3| | 3| 2| +--+----+ | 3| 1| | 4| 1| +--+----+ +--+----+ ``` 結果のイメージとしては ```ここに言語を入力 +--+----+----+----+ |id|name|avol|bvol| +--+----+----+----+ | 1|aaaa| 1|null| | 2|bbbb| 3| 3| | 3|cccc| 6| 3| | 4|dddd|null| 1| +--+----+----+----+ ``` 上記の結果になるように初心者なりにWEBを見ながら試行錯誤し下記のようなsqlを考えてみたのですが、ほしい結果と違う結果しか出ず困っています。 ``` SELECT c.id, c.name, SUM(tmp.avol) as avol, SUM(tmp.bvol) AS bvol FROM ( SELECT a.id AS aid, b.id AS bid, a.avol AS avol, b.bvol AS bvol FROM a LEFT JOIN b ON a.id = b.id UNION SELECT a.id AS aid, b.id AS bid, a.avol AS avol, b.bvol AS bvol FROM a RIGHT JOIN b ON a.id= b.id ) AS tmp LEFT JOIN c ON c.id = tmp.aid OR c.id = tmp.bid GROUP BY id ORDER BY id ``` 上記のsqlを試すと ```ここに言語を入力 +--+----+----+----+ |id|name|avol|bvol| +--+----+----+----+ | 1|aaaa| 1|null| | 2|bbbb| 3| 2| | 3|cccc| 12| 9| | 4|dddd|null| 1| +--+----+----+----+ ``` どのようにしたら思った通りの結果が出ますでしょうか? もし、参考になるURL等ありましたら教えて頂けませんでしょうか? よろしくお願い致します。 ###補足情報(言語/FW/ツール等のバージョンなど) 10.1.10-MariaDB, php 5.6.9

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

snowfallerさんが既に回答しておりますが、
プログラムでもSQLでもそうなのですが、
一気に問題を解決しようとせずに、
段階的に問題を解決する習慣を付けることをお勧めします。

特にSQLは一気にクエリを作成すると、どの部分からデータ取得のされ方が想定と異なるのかを追いかけにくいため、
初学者のうちは手間がかかるとしても、
1つ1つの問題解決するクエリを作り、それを最後に1つにするアプローチを取るのが確実でしょう。

今回のケースでは行う必要のある要件は質問者さんの望む結果から汲み取ると以下となりますよね?

  1. AテーブルのIDごとにavolを合計する
  2. BテーブルのIDごとにbvolを合計する
  3. CテーブルのIDと一致する1.と2.の結果を取得する。ただし1.、2.のいずれか、または両方にCテーブルのIDが存在しない場合でもCテーブルのIDは全て表示する

これを上から1つずつ解決していきましょう。

###AテーブルのIDごとにavolを合計する
これだけだと質問者さんのレベルでも容易に実現できるかと思われます。

一応サンプルコードは以下となります。

SQL

1SELECT 2 id -- Cテーブルとの結合キー 3, SUM(avol) AS total_avol 4FROM 5 a 6GROUP BY 7 id

###BテーブルのIDごとにbvolを合計する
取得元がBテーブルになるだけで、
Aテーブルの時とやることは変わりませんね。

SQL

1SELECT 2 id -- Cテーブルとの結合キー 3, SUM(bvol) AS total_bvol 4FROM 5 b 6GROUP BY 7 id

###CテーブルのIDと一致する1.と2.の結果を取得する。ただし1.、2.のいずれか、または両方にCテーブルのIDが存在しない場合でもCテーブルのIDは全て表示する

恐らく質問者さんがネックとなったのはここですよね。
1つ1つ考え方を整理していきましょう。

欲しい結果としては、
Cテーブルの内容に+αで、AテーブルとBテーブルの合計結果をくっつけて表示したいのですよね?

この場合はCテーブルの結果を中心に考えるのでCテーブルが中心テーブルとなります。

中心テーブルとは、
別テーブルにより結合されるテーブルと考えてください。

SQLでは以下のイメージです。

SQL

1-- 内部結合の場合 2中心テーブル INNER JOIN 別テーブル 3-- 外部結合の場合 4中心テーブル LEFT JOIN 別テーブル

さて以下からはAテーブル合計と、
Bテーブル合計をそれぞれCテーブルにくっつける例を示していきます。

Aテーブルの合計値、Bテーブルの合計値をそれぞれ取ってくる場合ですが、
各テーブルの合計値結果を別テーブルとしてCテーブルにくっつける必要があります。

また、Cテーブルの内容は全て表示するという制約から外部結合(LEFT JOIN)を利用しなければなりません。

それをまとめると最終的は完成像は以下となります。

SQL

1SELECT 2 c.id 3, c.name 4, t1.total_avol AS avol 5, t2.total_bvol AS bvol 6FROM 7 c 8 LEFT JOIN ( 9 Aテーブル合計取得クエリ 10 ) t1 ON c.id = t1.id 11 LEFT JOIN ( 12 Bテーブル合計取得クエリ 13 ) t2 ON c.id = t2.id 14ORDER BY 15 c.id 16;

この完成像に対して、
後は質問者さん自身がそれぞれの合計取得SQLを埋め込んでいけば、
望んだ結果が得られると思われます。

###蛇足
質問者さん自身いろいろ試行錯誤したのかと思われますが、
掲示コードにある**「RIGHT JOIN句」**は一般的にはほぼ使われません。
あまり使われない理由として大きいのは以下2点です。

  • 大抵はLEFT JOINで代替可能
  • RIGHT JOIN句では中心テーブルを後ろ(右側)に書く必要があるので、一般的に可読性が悪い

投稿2016/08/26 22:02

編集2016/08/26 22:26
Panzer_vor

総合スコア1636

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akasuka

2016/08/27 04:11

ご丁寧にせつめいありがとうございます。 勉強になりますありがとうございます!
guest

0

ベストアンサー

段階的に考えていけばいいと思います。

  • まずは、表aと表bを一つの表にする。

SQL

1select a.id id, avol, NULL bvol from a 2union all select b.id id, NULL avol, bvol from b
+------+------+------+ | id | avol | bvol | +------+------+------+ | 1 | 1 | NULL | | 2 | 1 | NULL | | 2 | 2 | NULL | | 3 | 2 | NULL | | 3 | 3 | NULL | | 3 | 1 | NULL | | 2 | NULL | 1 | | 2 | NULL | 1 | | 2 | NULL | 1 | | 3 | NULL | 1 | | 3 | NULL | 2 | | 4 | NULL | 1 | +------+------+------+
  • 次にidごとにsumする。

SQL

1select id, sum(avol) avol, sum(bvol) bvol from ( 2 select a.id id, avol, NULL bvol from a 3 union all select b.id id, NULL avol, bvol from b 4) t1 group by id
+------+------+------+ | id | avol | bvol | +------+------+------+ | 1 | 1 | NULL | | 2 | 3 | 3 | | 3 | 6 | 3 | | 4 | NULL | 1 | +------+------+------+
  • そしてnameを付与する。

SQL

1select t2.id id, c.name name, t2.avol avol, t2.bvol from ( 2 select id, sum(avol) avol, sum(bvol) bvol from ( 3 select a.id id, avol, NULL bvol from a 4 union all select b.id id, NULL avol, bvol from b 5 ) t1 group by id 6) t2 7left outer join c on t2.id=c.id
+------+------+------+------+ | id | name | avol | bvol | +------+------+------+------+ | 1 | aaaa | 1 | NULL | | 2 | bbbb | 3 | 3 | | 3 | cccc | 6 | 3 | | 4 | dddd | NULL | 1 | +------+------+------+------+

投稿2016/08/26 16:33

snowfaller

総合スコア125

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akasuka

2016/08/27 04:10

解決出来ました! ありがとうございます!
guest

0

sql

1SELECT 2 a.id, 3 a.name, 4 (SELECT sum(b.val) FROM b WHERE b.id = a.id) b_val, 5 (SELECT sum(c.val) FROM c WHERE c.id = a.id) c_val 6FROM a

のようにサブクエリを使えば統計は簡潔にかけますよ

注意事項

  1. 処理速度のチェックはしてません
  2. 履歴テーブル(数値入り)に NULL が入っていることを想定してはいません

投稿2016/08/26 23:28

編集2016/08/26 23:32
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

書いてみました。

sql

1select c.id, c.name, a.avol, b.bvol 2from tableC as c 3left join (select id, sum(avol) avol from tableA group by 1) as a using(id) 4left join (select id, sum(bvol) bvol from tableB group by 1) as b using(id) 5order by 1,2;

投稿2016/08/27 02:45

A.Ichi

総合スコア4070

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

手元に MariaDB の環境が無いので、MySQLで動作確認してあります。

sql

1SELECT c.id, c.name, a.avol, b.bvol 2FROM table_c AS c 3LEFT OUTER JOIN ( 4 SELECT id, SUM(avol) AS avol FROM table_a GROUP BY id 5) AS a ON c.id = a.id 6LEFT OUTER JOIN ( 7 SELECT id, SUM(bvol) AS bvol FROM table_b GROUP BY id 8) AS b ON c.id = b.id 9ORDER BY c.id;

http://sqlfiddle.com/#!9/d249d6/10

投稿2016/08/26 16:48

編集2016/08/27 08:36
KiyoshiMotoki

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Panzer_vor

2016/08/26 21:00 編集

横から失礼致します。 メインクエリ(Cテーブル)に対する集約って不要ではないでしょうか? おそらく質問者さんのCテーブルの構造ではIDが主キーなると思われるので出力結果には変化はありませんが、CテーブルのIDに重複レコードがあると重複IDのレコード数×各テーブルの値合計となり合計結果値自体が変わってしまいます。
KiyoshiMotoki

2016/08/27 08:37

KotoriMaturi様 > メインクエリ(Cテーブル)に対する集約って不要ではないでしょうか? ご指摘ありがとうございます。 確かに、仰る通りですね。 回答を修正させていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問