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

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

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

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

Q&A

解決済

1回答

707閲覧

1レコードから複数(毎月)の集計を行うSQLの作成方法

planet

総合スコア11

MySQL

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

0グッド

2クリップ

投稿2019/08/21 05:09

編集2019/08/21 06:25

mysqlのバージョンは5.6.26です

1レコードから複数(毎月)集計を行うSQLをどう作成すればよいか考えております。

現在のSQL文はこのようになっています。

SQL

1SELECT DATE_FORMAT(UserInsertDate, '%m') UserInsertDate, RegistrationCode RegistrationCode, count(RegistrationCode) count 2FROM user_info_table 3WHERE DATE_FORMAT(UserInsertDate, '%Y%m') < DATE_FORMAT(UpdateDate, '%Y%m') 4GROUP BY DATE_FORMAT(UserInsertDate, '%m'), RegistrationCode

現在このSQL文ですと、user_info_table1レコードにつきcount1件しか取得できませんが、
DATE_FORMAT(UserInsertDate, '%Y%m')< DATE_FORMAT(UpdateDate, '%Y%m')の全てのレコードの月をcount1件として取得したいのですがどのようにすればよいでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

年+月のデータを使って集計したいなら別途カレンダーテーブルをつくって
ダミーで100年分くらいデータを作っておき、joinすればよいでしょう

具体的には命題の情報では回答が難しいので
サンプルをcreate table+insert形式で例示ください

追記

SQL

1create table user_info_table(id int primary key,UserInsertDate date,UpdateDate date,RegistrationCode int); 2insert into user_info_table values 3(1,'20190401','20191001',1);

というレコードが1つしかないテーブルから

年月RegistrationCodeカウント
4月11
5月11
6月11
7月11
8月11
9月11
10月11

という結果を発生させるのですか?
カウントが1の理由がわかりません

procedure

この手の処理はprocedureを使ってテンポラリーテーブルを作って処理します

  • 元データ

SQL

1create table user_info_table(id int primary key,UserInsertDate date,UpdateDate date,RegistrationCode int); 2insert into user_info_table values 3(1,'20190401','20191001',1), 4(2,'20190301','20190801',1), 5(3,'20190401','20190601',2);
  • procedure作成

1回だけ以下を実行

SQL

1create table user_info_table(id int primary key,UserInsertDate date,UpdateDate date,RegistrationCode int); 2insert into user_info_table values 3(1,'20190401','20191001',1), 4(2,'20190301','20190801',1), 5(3,'20190401','20190601',2); 6; 7 8drop procedure if exists proc_test; 9delimiter // 10create procedure proc_test() 11begin 12declare a int; 13declare b date; 14declare c date; 15declare d int; 16declare done int default 0; 17declare cur cursor for 18select id,UserInsertDate,UpdateDate,RegistrationCode from user_info_table; 19declare continue handler for sqlstate '02000' set done = 1; 20set @sql=""; 21open cur; 22repeat 23fetch cur into a,b,c,d; 24 if not done then 25 set @date=b; 26 while @date<=c do 27 if @sql="" then 28 create temporary table tmp(nengetu date,RegistrationCode int); 29 set @sql="insert into tmp "; 30 else 31 set @sql=concat(@sql,"union all "); 32 end if; 33 set @sql=concat(@sql,"select '",@date,"',",d," "); 34 set @date=@date + interval 1 month; 35 end while; 36 end if; 37 until done end repeat; 38close cur; 39PREPARE stmt from @sql; 40EXECUTE stmt; 41end 42// 43delimiter ;
  • テスト

SQL

1call proc_test; 2select * from tmp;
nengetuRegistrationCode
2019-04-011
2019-05-011
2019-06-011
2019-07-011
2019-08-011
2019-09-011
2019-10-011
2019-03-011
2019-04-011
2019-05-011
2019-06-011
2019-07-011
2019-08-011
2019-04-012
2019-05-012
2019-06-012
  • 集計

SQL

1call proc_test; 2select nengetu,RegistrationCode,count(*) as cnt from tmp 3group by nengetu,RegistrationCode; 4
nengetuRegistrationCodecnt
2019-03-0111
2019-04-0112
2019-04-0121
2019-05-0112
2019-05-0121
2019-06-0112
2019-06-0121
2019-07-0112
2019-08-0112
2019-09-0111
2019-10-0111

カレンダーを利用

SQL

1create table user_info_table(id int primary key,UserInsertDate date,UpdateDate date,RegistrationCode int); 2insert into user_info_table values 3(1,'20190401','20191001',1), 4(2,'20190301','20190801',1), 5(3,'20190401','20190601',2); 6 7/*とりあえず1年分投入してますが、使い回すので100年分くらい投入しておくとよい*/ 8create table nengetu(d date unique); 9insert into nengetu values 10('20190101'), 11('20190201'), 12('20190301'), 13('20190401'), 14('20190501'), 15('20190601'), 16('20190701'), 17('20190801'), 18('20190901'), 19('20191001'), 20('20191101'), 21('20191201');
  • 集計

SQL

1select d,RegistrationCode,count(*) as cnt from user_info_table as t1 2inner join nengetu as t2 3on t2.d between t1.UserInsertDate and t1.UpdateDate 4group by d,RegistrationCode 5order by d,RegistrationCode;

投稿2019/08/21 06:06

編集2019/08/28 06:12
yambejp

総合スコア114843

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

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

planet

2019/08/21 06:21

ご回答ありがとうございます。ドロップダウンリストから年を選択させるので、1年分のデータで大丈夫です。 あと、こちらの不手際で申し訳ありませんでしたが、毎月のレコードの作成ではなく集計でした。タイトルも紛らわしいので修正致します。
yambejp

2019/08/21 06:36

すみません、回答の意図が伝わってないかもしれませんので レコードのサンプルと、期待する結果を提示いただかないと 具体的なSQLが書けないということです。 回答を希望するなら是非サンプル提示を検討ください
planet

2019/08/21 06:47

年月,RegistrationCode1.カウント 1月,1,13 2月,1,34 3月,1,23 4月,1,12 …… 12月1,23 こんな感じです。よろしくお願いします。
yambejp

2019/08/21 07:01

user_info_tableの情報がないと無理です
planet

2019/08/21 07:10 編集

失礼 UserInsertDate,UpdateDate,RegistrationCode 20190401,20191001,1 このデータの場合は 年月,RegistrationCode.カウント 4月,1,1 5月,1,1 6月,1,1 7月,1,1 8月,1,1 9月,1,1 10月,1,1 こうなるようにお願いします。
yambejp

2019/08/21 08:42

ちょっと意味がわかりません 追記した箇所を読んで、それでいいのか確認してください
kirato

2019/08/22 01:30

もしかして UserInsertDate,UpdateDate,RegistrationCode 20190401,20191001,1 20190401,20190801,1 このデータの場合は 年月,RegistrationCode.カウント 4月,1,2 5月,1,2 6月,1,2 7月,1,2 8月,1,2 9月,1,1 10月,1,1 ってなるってことですか?
yambejp

2019/08/22 04:34

年月なのか複数年分あっても月が同じであれば一緒に集計するのか そのあたりも気になります。 > 1年分のデータで大丈夫 ということなので、絶対に年をまたがないという制限がかかっているのでしょうか? たとえば4月から翌年3月まででも、1~12月みたいな時系列とはいえない表示でよいのでしょうか?
planet

2019/08/28 00:42

凄く返事が遅くなって申し訳ありません。 kiratoさんの書き込みの通りの結果となります。 時系列で言えば UserInsertDate,UpdateDate,RegistrationCode 20181001,20190401,1 この場合で、選択年度が2019であれば 1月,1,1 2月,1,1 3月,1,1 4月,1,1 となります。 遅くなりましたが、よろしくお願いします。
yambejp

2019/08/28 01:09

仮に 20181001,20191201,1 のような場合はどうなのでしょう? (1)13ヶ月以上にはぜったいならない (2)10,11,12月がカウント2になる (3)気にせずにカウントは1
planet

2019/08/28 01:15

質問ありがとうございます。 13か月以上絶対ならないというよりも、カウントの年をドロップダウンで指定するので、その年のカウントが1になります。 20181001,20191201,1 の例で行くと、2018年の指定で行くと、2018年10月分の1のみカウントされます。 その場合、2018年1月~2018年12のカウント数しか気にしなくても大丈夫です。
yambejp

2019/08/28 02:18

一応procedureの書き方を追記しておきました きちんとサンプル提示してくれないので仕様がさっぱりわかりません 今回の回答もあっているかどうかわかりませんが とりあえず形にはしておきました
planet

2019/08/28 06:00

その回答で合っています。ただし、procedureを利用したやり方は、恐らく使えないと思いますが。 しっかりと作り方を提示して頂いたyambejpさんをベストアンサーとします。ありがとうございました。 私ももっと質問の仕方や条件の提示を上手くならないといけないですね。そこが反省点です。 また、SQLとは別のコーディングのやり方で解決しました。質問と意図が違うので解決方法を載せる意味が無いと思うのでこれで終了とさせて頂きます。
yambejp

2019/08/28 06:13

procedureがダメなら最初にかいたとおりカレンダーテーブルを 用意して利用するのが妥当 追記してありますので参考にしてください
planet

2019/08/28 06:20

わざわざありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問