🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

683閲覧

SQL(SQL Server)で、特定の順番に並んでいるレコードについて、特定の条件の値が現れるところまでを1ブロックとして合計値を出したい

BrandNewMenu

総合スコア1

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2020/12/11 15:40

編集2020/12/11 16:25

前提・実現したいこと

SQL(SQL Server)で、特定の順番に並んでいるレコードについて、値の合計値を取得したいです。
ただし、特定の条件の値が現れるところまでを1ブロックとして合計値を出したいです。

test_table1

timegroup_namevalue
00:30groupA10
01:30groupA20
03:30groupA130
05:30groupA30
07:30groupA40
09:30groupA70
00:30groupB30
01:30groupB50

例えば、group_name毎に合計値を算出しますが、その中でも「100以上のvalueが現れるまで」を1ブロックとするとします。
そうすると、groupAは、03:30の130が現れるところでブロックが分かれますので、
10, 20のブロックと30, 40, 70の2つのブロックに分かれます。

これらの合計値は、10 + 20 = 30, 30 + 40 + 70 = 140
となり、30と140という合計値になります。
この内の大きい方を求めるとして、結果は140となります。

groupBは、100以上の値がありませんので、全てを合計することになり、30 + 50 = 80
となり、結果は80となります。

テーブル作成およびデータ挿入は下記です。

SQL

1CREATE TABLE test_table1( 2 time TIME, 3 group_name NVARCHAR(10), 4 value INT 5); 6 7INSERT INTO test_table1 (time, group_name, value) 8VALUES 9('00:30', 'groupA', 10), 10('01:30', 'groupA', 20), 11('03:30', 'groupA', 130), 12('05:30', 'groupA', 30), 13('07:30', 'groupA', 40), 14('09:30', 'groupA', 70), 15('00:30', 'groupB', 30), 16('01:30', 'groupB', 50)

まずは中間結果として、valueが100以上のところで区切って、group_name毎のvalueの合計値を出したいです。

group_namevalueの合計
groupA30
groupA140
groupB80

そして、同じgroup_nameの場合は最大値の方を最終結果とし、下記としたいです。

group_namevalueの合計
groupA140
groupB80

試したこと

テーブルにサブグループIDの列を追加し、valueが100以上の場合にカウントアップするようにし、以下のテーブルを作れば求められると考えました。

test_table2

timegroup_namevaluesub_gid
00:30groupA101
01:30groupA201
03:30groupA1302
05:30groupA302
07:30groupA402
09:30groupA702
00:30groupB302
01:30groupB502

SQL

1SELECT group_name, MAX(total) 2FROM ( 3 SELECT group_name, sub_gid, SUM(value) AS total 4 FROM test_table2 5 WHERE value < 100 6 GROUP BY group_name, sub_gid 7) AS tmp_tbl 8GROUP BY group_name

しかし、test_table1からtest_table2をSQLで作る方法が分かりませんでした。
別の方法でも構いませんので、特定の条件でブロックを分けるとして、そこまでの合計を算出する
SQLを教えていただきたくお願いします。

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

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

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

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

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

gentaro

2020/12/11 15:49

質問文がややこしくて最終的に欲しい結果セットの形がわかりづらいので、それを質問文に書いてください。 あとSQLの質問を投げる時は、そのテーブルを作成するCREATE文とINSERT文を質問文に貼っておけば、回答者が気軽に試して回答しやすくなります。
BrandNewMenu

2020/12/11 16:25

慣れておらず申し訳ありません。記載しました。
guest

回答2

0

ベストアンサー

test_table2 は以下で求められますね。

SQL

1SELECT * 2 , COUNT(CASE WHEN value >= 100 THEN 1 END) 3 OVER(PARTITION BY group_name ORDER BY time) AS sub_gid 4from test_table1

投稿2020/12/12 02:24

sazi

総合スコア25327

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

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

BrandNewMenu

2020/12/12 12:44

ありがとうございます。教えていただいたものの方が私のものよりもシンプルですね。 SQLがよく分かっていないのですが、COUNT(CASE WHEN .. THEN .. END)で、THENの値には意味がなく、CASEにマッチした回数をカウントしているということで良いでしょうか? また、OVER()にしたことで、累積のマッチ回数が出ているという解釈で良いでしょうか?
sazi

2020/12/12 14:51 編集

>THENの値には意味がなく COUNTですからその通りです。逆にelseを省略してNullを生じさせる事に意味があります。 マッチさせているのはcaseで、over()内でorder by でtimeを指定する事で、time順でのマッチの累積となります。
BrandNewMenu

2020/12/13 06:55

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

0

valueが100以上の場合に1を立てておき、SUM() OVER()でその累積値を出せば良い気がしました。

SQL

1WITH test_table2 AS ( 2SELECT *, SUM(tmp) OVER(PARTITION BY group_name ORDER BY group_name, time ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS sub_gid 3FROM ( 4 SELECT *, CASE WHEN value >= 100 THEN 1 ELSE 0 END AS tmp 5 FROM test_table1 6) AS tmp_tbl1 7) 8SELECT group_name, MAX(total) 9FROM ( 10 SELECT group_name, sub_gid, SUM(value) AS total 11 FROM test_table2 12 WHERE value < 100 13 GROUP BY group_name, sub_gid 14) AS tmp_tbl2 15GROUP BY group_name

間違っている、またはもっと良い方法があれば教えてください。

投稿2020/12/11 16:16

BrandNewMenu

総合スコア1

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問