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

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

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

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

SQL

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

Q&A

解決済

7回答

16435閲覧

SQLで日付を持ったデータの集計を行いたい

hos

総合スコア33

SQL Server

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

SQL

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

0グッド

0クリップ

投稿2016/07/27 07:09

編集2016/07/27 07:47

SQL(SQL Server)で日付を持ったデータの集計をしています。
開始日時と終了日時を持ったデータに対し、1ヶ月分、23時59分59秒に、
開始されていて終了されていないデータの件数を一覧にしたいのですが
うまい方法が思いつきません。

データはごく簡単に書くと以下のようなテーブルです。

CREATE TABLE hoge ( ID int PRIMARY KEY, 開始日時 datetime2(0), 終了日時 datetime2(0), --終了していない場合はNULL )

1日分を持ってくるのは以下のような感じで考えています。

SQL

1DECLARE @対象日時 datetime2(0) 2 SET @対象日時 = '2016-07-22 23:59:59' 3 4SELECT COUNT(*) AS5 FROM hoge 6 WHERE 開始日時 <= @対象日時 7 AND (終了日時 < @対象日時 OR 終了日時 IS NULL)

日付マスタのようなものはあるので、そこで1ヶ月分の日付のリストを作成し、LEFT OUTER JOIN させるようなことを考えています。

ループさせるのではなくSQLで解決させるにはどうすればよいでしょうか?

どのような結果が欲しいか追記します。

たとえば、下記のようなレコードがあった場合

ID,開始日時,終了日時 1,"2016-04-02 01:00:00","2016-04-05 01:00:00" 2,"2016-04-04 01:00:00",NULL

結果としては

日付,件数 "2016-04-01", 0 //1件もない "2016-04-02", 1 //1のデータのみ "2016-04-03", 1 //1のデータのみ "2016-04-04", 2 //1と2のデータ "2016-04-05", 1 //1のデータは23:59:59には終了していて2のデータのみ "2016-04-06", 1 //2のデータのみ

といった感じになります。日付のところは、上記の例だと

SQL

1SELECT 日付 FROM 日付マスタ WHERE 日付 BETWEEN '2016-04-01' AND '2016-04-06'

というように取り出せます。

わかりにくくて申し訳ありませんがよろしくお願いいたします。

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

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

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

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

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

dupont_kedama

2016/07/27 07:28

希望する結果セットの例を提示していただいた方が良いと思います。
guest

回答7

0

期待する結果から考えるとこんな感じでしょうか?
1か月分が当月なのか前月なのか任意なのかがわからないので
とりあえず手入力で書いておきます

SQL

1SELECT 2 T2.日付 3 , COUNT(*) AS4FROM hoge T1 5LEFT JOIN 日付マスタ T2 6-- 日付マスタの日付が開始日時以降 7ON T2.日付 >= CAST(T1.開始日時 AS DATE) 8-- 日付マスタの日付が終了日時の0時0分より前 か 終了日時が設定されていない 9AND (T2.日付 < CAST(T1.終了日時 AS DATE) OR T1.終了日時 IS NULL) 10AND T2.日付 BETWEEN '2016-04-01' AND '2016-04-06' 11GROUP BY 12 T2.日付 13

投稿2016/08/02 06:54

kutsulog

総合スコア985

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

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

0

こんばんは。
要望の出力を行うのでしたら最終的に下記のような形のSQLに持ち込めれば良さ気です。

SQL

1SELECT 2 T.日付 3, T.件数 4FROM 5 ( 6 SELECT 7 M.日付 8 , SUM( 9 CASE 10 WHEN H.開始日時 IS NOT NULL 11 THEN 1 12 ELSE 0 13 END 14 ) AS 件数 15 FROM 16 日付マスタ M 17 LEFT JOIN HOGE H 18 ON M.日付 BETWEEN H.開始日 AND COALESCE(H.終了日, 月末日) 19 GROUP BY 20 M.日付 21 ) T 22WHERE 23 T.日付 BETWEEN 検索条件:開始日 AND 検索条件:終了日 24ORDER BY 25 T.日付

SQLの結合所条件の部分は、
終了日時NULLを考慮して月末日を入れる形を取ってますが、
この箇所は検索条件のTO条件と一致させても良いと思います。

一応月内の最終日まで表示することを考慮して月末日とは書いておりますが・・・
後、開始日、終了日の項目は時間部を切り捨てていることを前提として書いてますので悪しからず・・・

###追記
SQL内のSUM関数使っている所ですが、
列名指定のCOUNTはNULLはカウント対象外となるので、
A.Ichiさん掲示のコードのように**COUNT(開始日時)**で事足りますね。

投稿2016/07/27 15:56

編集2016/07/27 22:50
Panzer_vor

総合スコア1636

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

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

0

とりあえず1ヶ月は手入力で

SQL

1select cast(c.日付 as date) 日付, count(h.開始日時) 件数 2from 日付マスタ c left join hoge h on cast(c.日付 as date) >= cast(h.開始日時 as date) and 3(h.終了日時 is null or cast(c.日付 as date) <= h.終了日時) 4where c.日付 between '2016-04-01' and '2016-04-06' 5group by 1

投稿2016/07/27 12:55

編集2016/07/27 23:43
A.Ichi

総合スコア4070

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

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

0

1か月分の終了してないデータをサブクエリで絞り込む。
この際、開始時刻は年月日の形式に変換しておく。
上記を from にし、年月日を group by して
あとは年月日ごとに count すればいける感じ!?

// ご希望の内容を勘違いしてたら申し訳ない。
--- 追加 ---

修正された質問を拝見しました。

テーブルと(必要な分の)日付マスタを cross join して
該当レコード(マスタ由来の日付が範囲内にある)を選別して
マスタ由来の日付で gropu by して count した結果と
日付マスタ(必要な分)を組み合わせればいけそうですが…

正直なところ、そこまで面倒なことをするくらいなら
すなおにループしますね。自分だったら。

投稿2016/07/27 07:22

編集2016/07/27 09:26
takasima20

総合スコア7458

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

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

hos

2016/07/27 07:51

ありがとうございます。 ご回答いただいた方法だと開始時刻での集計になる感じだと思います。 もうすこしやりたいことを追記いたしました。
guest

0

結局うまくいかず、1日ごとデータを取込みました。

投稿2017/06/02 06:35

hos

総合スコア33

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

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

0

結局うまくいかず、1日ごと処理を行うことにしました。

投稿2017/06/02 06:34

hos

総合スコア33

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

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

0

ベストアンサー

予めカレンダーテーブルを用意しておかないかぎり、
データの無い日付を抽出することはできません。
予め10年分くらいの有効日付を投入しておけばよいかと

投稿2016/07/27 08:52

yambejp

総合スコア114747

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問