2017-11-29 13 views
0

私のアプリケーションで問題を解決するには、洗練されたソリューションが必要です。異なるイベントで時間のギャップを取得するためのSQLクエリ

私はこのようなテーブルを持っている:

ItemId | StartDateTime  | EndDateTime   | StartState | EndState 
    1 | 2017-01-01 12:00:00 | 2017-01-01 12:30:00 |  1  | 0 
    1 | 2017-01-03 08:00:00 | 2017-01-03 09:00:00 |  0  | 1 
    1 | 2017-01-08 10:00:00 | 2017-01-08 10:30:00 |  1  | 1 
    1 | 2017-01-15 14:00:00 | 2017-01-14 10:30:00 |  1  | 0 
    1 | 2017-02-01 09:30:00 | 2017-02-01 10:00:00 |  0  | 1 

私は月に0から1にEndState間のすべてのギャップを合計するクエリを必要としています。 (フル月実施)の項目が月に0にのみEndStateを持って

  1. 項目のみを持っているとき: は当時、私はさまざまな条件のためのギャップを取得するためにC#でループを実行しますEndStateが1になるまで
  2. アイテムがEndStateを1にして1ヶ月間EndStateを1にしたとき(EndDateTimeと月末の間のギャップ)
  3. StartStateを月の0(月の始まりとEndDateTimeの間のギャップ)に設定します。

この情報は、単一のクエリまたはストアドプロシージャを使用してC#でループすることは可能ですか?

+2

提供されたデータまたは別のサンプルデータセットのいずれかを使用して、必要性を説明できる例がありますか?たとえば、あなたの要件を考えれば、あなたのテーブルの5つのエントリから予想される結果はどうなりますか? – Forty3

+0

私の悪い説明には申し訳ありません。したがって、私が求めている結果は次のとおりです。 アイテム1は19日、6時間30分に1月に出荷されます (1d 20h 30m 01/01/2017 12:30:00から03/01/2017 09 :00:00プラス17d 10h from 14/01/2017 10:30:00〜01/02/2017 00:00:00末) – Rotondof

答えて

1

私はあなたのスタートを与えることができます - それは、開始/終了時間内であれば月末を解釈するあなたの条件はあなたに委ねられている。

<!-- language: lang-sql --> 
;with ordered(itemid, startdatetime, enddatetime, startstate, endstate, rownum) as (
    select *, row_number() over (partition by itemid 
           order by itemid, startdatetime) 
     from inventory 
), 
goneOut(itemid, startdatetime, enddatetime, startstate, endstate, rownum) as (
    select goneOut.* 
     from ordered goneOut 
    where goneOut.startstate = 1 and goneOut.endstate = 0 
), 
comeBack(itemid, startdatetime, enddatetime, startstate, endstate, rownum) as (
    select goneOut.* 
     from ordered goneOut 
    where goneOut.startstate = 0 and goneOut.endstate = 1 
), 
rangeOut (itemid, goneOutRowNum, comeBackRowNum) as (
    select goneOut.itemid, goneOut.rownum, min(comeBack.rownum) 
     from goneOut 
      inner join comeBack 
       on goneOut.itemid = comeBack.itemid 
       and goneOut.rownum < comeBack.rownum 
    group by goneOut.itemid, goneOut.rownum 
), 
rangeTimeBits (itemid, startdatetime, enddatetime, totalMinutes, days, hours, minutes) as (
    select r.itemid, g.enddatetime, c.enddatetime, 
      DATEDIFF(MINUTE, g.enddatetime, c.enddatetime), 
      DATEDIFF(MINUTE, g.enddatetime, c.enddatetime)/(24 * 60), 
      DATEDIFF(MINUTE, g.enddatetime, c.enddatetime) % (24 * 60)/60, 
      DATEDIFF(MINUTE, g.enddatetime, c.enddatetime) % (24 * 60) % 60 
     from rangeOut r 
      inner join goneOut g on r.itemid = g.itemid and r.goneOutRowNum = g.rownum 
      inner join comeBack c on r.itemid = c.itemid and r.comeBackRowNum = c.rownum 
) 
select * from rangeTimeBits 

最終選択はあなたを与えるだろう項目が0の状態の開始/終了時間と各停止の個々の日/時間/分内訳。確かに、この時点から、月末をフィルタリングしたり、個々の品目の停止を集計する方法を確認できます。

itemid startdatetime   enddatetime    totalMinutes days hours minutes 
1  2017-01-01 12:30:00.000 2017-01-03 09:00:00.000 2670   1 20 30 
1  2017-01-14 10:30:00.000 2017-02-01 10:00:00.000 25890  17 23 30 
+0

ありがとう@ Forty3、私はそれが素晴らしいスタートだと思います。 – Rotondof

関連する問題