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

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

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

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

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

Q&A

解決済

3回答

10185閲覧

[SQL] SELECT句にWHILEを適用する方法

Daiki-Kawanuma

総合スコア29

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

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

0グッド

1クリップ

投稿2015/10/07 02:12

SQL Server 2014 Management Studioを使用しています。

SELECT date, classification, validation, CASE WHEN arrivalTime BETWEEN '00:00' AND '00:10' THEN energy ELSE 0 END AS '00:00', CASE WHEN arrivalTime BETWEEN '00:10' AND '00:20' THEN energy ELSE 0 END AS '00:10', CASE WHEN arrivalTime BETWEEN '00:20' AND '00:30' THEN energy ELSE 0 END AS '00:20', ・・・ FROM Energy_date

上記クエリのように1日を10分刻みに分けたタイムスロットで条件分けをした結果を出力しています。
このクエリだと、6(1時間=10分×6)* 24(24時間)= 144個分のカラムの式を書かないといけなく、クエリがかなり長くなっています。

クエリのSELECT句にWHILEなどを適用してスッキリさせる方法はありますでしょうか?
よろしくお願いします。

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

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

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

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

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

yuba

2015/10/07 03:09

Energy_dateは何を主キーに持つテーブルですか? classification, validationはどういった情報を持つカラムですか? また、細かいことですがarrivalTime のデータ型はなにになりますか?
guest

回答3

0

ベストアンサー

WHILEを使ってSQLを書こうとすると以下のような感じで
varcharの変数に少しずつ足して動的SQLとして実行することになります。

ここで1つのvarchar変数の最大文字数は8000文字のため
複数用意して実行時に連結する必要があるので注意してください。

SQL

1BEGIN 2 3 SET QUOTED_IDENTIFIER OFF 4 5 DECLARE @hour int 6 DECLARE @min int 7 DECLARE @sql1 varchar(max) = '' 8 DECLARE @sql2 varchar(max) = '' 9 DECLARE @sql3 varchar(max) = '' 10 DECLARE @sql4 varchar(max) = '' 11 DECLARE @sql5 varchar(max) = '' 12 DECLARE @sql6 varchar(max) = '' 13 DECLARE @start char(5) 14 DECLARE @end char(5) 15 16 SET @hour = 0 17 SET @sql1 = "SELECT" 18 + ' date' 19 + ' ,classification' 20 + ' ,validation' 21 WHILE @hour < 24 22 BEGIN 23 SET @min = 0 24 WHILE @min < 60 25 BEGIN 26 SET @start = RIGHT("00" + CAST(@hour AS VARCHAR), 2) + ":" 27 + RIGHT("00" + CAST(@min AS VARCHAR), 2) 28 SET @end = RIGHT("00" + CAST(@hour AS VARCHAR), 2) + ":" 29 + RIGHT("00" + CAST(@min + 9 AS VARCHAR), 2) 30 -- 時間の重なっている部分を両方に出すならこちら 31 -- SET @end = RIGHT("00" + CAST(@hour AS VARCHAR), 2) + ":" 32 -- + RIGHT("00" + CAST((@min + 10) % 60 AS VARCHAR), 2) 33 IF @hour < 6 34 BEGIN 35 SET @sql2 = @sql2 36 + " ,CASE WHEN arrivalTime" 37 + " BETWEEN '" + @start + "' AND '" + @end + "'" 38 + " THEN energy" 39 + " ELSE 0" 40 + " END AS '" + @start + "'" 41 END 42 ELSE IF @hour < 12 43 BEGIN 44 SET @sql3 = @sql3 45 + " ,CASE WHEN arrivalTime" 46 + " BETWEEN '" + @start + "' AND '" + @end + "'" 47 + " THEN energy" 48 + " ELSE 0" 49 + " END AS '" + @start + "'" 50 END 51 ELSE IF @hour < 18 52 BEGIN 53 SET @sql4 = @sql4 54 + " ,CASE WHEN arrivalTime" 55 + " BETWEEN '" + @start + "' AND '" + @end + "'" 56 + " THEN energy" 57 + " ELSE 0" 58 + " END AS '" + @start + "'" 59 END 60 ELSE 61 BEGIN 62 SET @sql5 = @sql5 63 + " ,CASE WHEN arrivalTime" 64 + " BETWEEN '" + @start + "' AND '" + @end + "'" 65 + " THEN energy" 66 + " ELSE 0" 67 + " END AS '" + @start + "'" 68 END 69 SET @min = @min + 10 70 END 71 SET @hour = @hour + 1 72 END 73 74 SET @sql6 = " FROM Energy_date" 75 76 EXEC(@sql1 + @sql2 + @sql3 + @sql4 + @sql5 + @sql6) 77END 78

投稿2015/10/08 04:27

編集2015/10/08 09:48
kutsulog

総合スコア985

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

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

Daiki-Kawanuma

2015/10/08 08:54

正に探していた方法です!!ありがとうございます。 クエリを文字列連結して発行できるとは知りませんでした。とても参考になります。 ただ、varcharが上限8000文字というのがなんとも・・・そこらへんはDBMSで解決してくれれば嬉しいですね; ご回答を頂き誠にありがとうございました。 ベストアンサーにさせて頂きます。
guest

0

SQLの時間データを15分単位で集計できますか?

リンク先、ちょっと古いものですが、、、^^;
こちらは15分単位ですが、その部分を10分に換算すれば出来そう。

投稿2015/10/07 05:47

kaputaros

総合スコア1844

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

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

Daiki-Kawanuma

2015/10/08 08:51

ご回答ありがとうございます。 リンクを拝見させて頂きました。私の記述が不十分だったのですが、arrivalTimeは10分単位で見ても離散的な値をしておりまして、リンクの方法ですと時間軸で見たときに歯抜けのデータが出力されることになります。
guest

0

本筋と関係ないところからで恐縮ですが、、、

00:00~00:10 を 00:00
00:10~00:20 を 00:10

2つの境界になる 00:10 は 00:00 と 00:10 のどちらとされたいですか?

恐らく時間の範囲は 00:00 ~ 23:59 だと思いますが
厳密に 00:00:00 ~ 23:59:59 で考えておいた方がよいと思いますので

00:00:00 ~ 00:09:59 を 00:00:00
00:10:00 ~ 00:19:59 を 00:10:00



23:50:00 ~ 23:59:59 を 23:50:00

なのかなーと思いまして

・・・というのを踏まえて

while での解決方法はさっぱりわかりませんが、時間幅(hh:m0:ss~hh:m9:ss)と欲しい結果(hh:m0:00)の関係を考えると、単純に arrivalTime(恐らくtime型?) の分の1桁から下を0に丸めれば・・・ってのはダメしょうか?

ぜんぜん見当違いのことを言ってたらご容赦ください

投稿2015/10/07 04:48

takito

総合スコア3111

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

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

Daiki-Kawanuma

2015/10/08 08:49

BETWEENは>= AND <=ですよね!; 複数時刻に含める意図はないので適切に境界を設定する必要がありました。 ご意見ありがとうございます。 私の記述が不十分だったのですが、arrivalTimeは10分単位で見ても離散的な値をしておりまして、arrivalTimeを用いて集計を行った場合、時間軸で見たときに歯抜けのデータが出力されてしまいます。 記述不十分で申し訳ありませんでした
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問