web-dev-qa-db-ja.com

SQLサーバーの日付範囲によるT-SQLからグループへの時間間隔の変更

元のテーブルには、Timestamp with Intervalという列があります。

間隔:タイムスタンプ自体でソートした場合の、現在と以前のタイムスタンプの分単位の差

Timestamp               Interval(InMinute)
2016-12-31 00:28:00     NULL
2016-12-31 00:29:00     1
2016-12-31 00:30:00     1
2016-12-31 00:45:00     15
2016-12-31 01:00:00     15
2016-12-31 01:15:00     15
2016-12-31 01:16:00     1
2016-12-31 01:17:00     1
2016-12-31 01:18:00     1
2016-12-31 01:19:00     1

T-SQLを使用して時間間隔の変化を検出し、出力を生成したい

StartDate                EndDate                Interval
2016-12-31 00:28:00      2016-12-31 00:30:00    1
2016-12-31 00:30:00      2016-12-31 01:15:00    15
2016-12-31 01:15:00      2016-12-31 01:19:00    1

インターバルが同じままだった期間を教えてください。 2番目の行は、2016-12-31 00:30:00から2016-12-31 01:15:00まで、間隔は同じ、つまり15であったことを示していますが、2016-12-31 01:15:00の後で1に戻りました。

4
HighAbove

itzik Ben Gan(シーケンスのギャップとアイランド)の例があります。これは、この記事のベースです。 Gaps

DECLARE @vt_Source AS TABLE
( ts datetime NOT NULL PRIMARY KEY,
 interval tinyint NULL
)

INSERT INTO @vt_Source(ts, interval)
VALUES('2016-12-31 00:28:00',     NULL)
,('2016-12-31 00:29:00'  ,   1)
,('2016-12-31 00:30:00'  ,   1)
,('2016-12-31 00:45:00'  ,   15)
,('2016-12-31 01:00:00'  ,   15)
,('2016-12-31 01:15:00'  ,   15)
,('2016-12-31 01:16:00'  ,   1)
,('2016-12-31 01:17:00'  ,   1)
,('2016-12-31 01:18:00'  ,   1)
,('2016-12-31 01:19:00'  ,   1)


SELECT
   min(ts_prev) AS startDate
  ,max(ts) AS endDate
  ,interval
FROM
   (SELECT
         ts
         ,interval
         ,ROW_NUMBER() OVER(ORDER BY ts ASC) AS  rn_all
         ,ROW_NUMBER() OVER(PARTITION BY interval ORDER BY ts ASC) AS rn_group
         ,LAG(ts,1,ts) OVER(ORDER BY ts ASC) AS ts_prev
    FROM
        @vt_Source
   )A
WHERE
   A.interval IS NOT NULL
GROUP BY
   rn_all - rn_group
   ,interval
ORDER BY 
   startDate ASC

このための出力:

startDate           endDate          interval
31/12/2016 00:28:00 31/12/2016 00:30:00 1
31/12/2016 00:30:00 31/12/2016 01:15:00 15
31/12/2016 01:15:00 31/12/2016 01:19:00 1

WHERE句を追加して、最初の行(インターバル列にNULLがある行)を削除しました

http://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=fe1888d0a934d73de0ed9887aaf4d482

4
Sabin Bio

SQL Server 2012以降を使用している場合は、LEAD関数も使用できます。

LEADは、関数のPARTITION BYORDER BYに基づいて、次のレコードの列の値を取得します。このデータセット内では、何にも分割されていませんが、ts値に基づいて並べています。

他の答えで一時テーブルを使用して、これを試してください:

DECLARE @vt_Source AS TABLE
( ts datetime NOT NULL PRIMARY KEY,
 interval tinyint NULL
)

INSERT INTO @vt_Source(ts, interval)
VALUES('2016-12-31 00:28:00',     NULL)
,('2016-12-31 00:29:00'  ,   1)
,('2016-12-31 00:30:00'  ,   1)
,('2016-12-31 00:45:00'  ,   15)
,('2016-12-31 01:00:00'  ,   15)
,('2016-12-31 01:15:00'  ,   15)
,('2016-12-31 01:16:00'  ,   1)
,('2016-12-31 01:17:00'  ,   1)
,('2016-12-31 01:18:00'  ,   1)
,('2016-12-31 01:19:00'  ,   1)


;WITH NextInterval AS (
    SELECT 
        vs.ts
        ,vs.interval
        ,LEAD(vs.interval,1) OVER(ORDER BY vs.ts) AS next_interval
    FROM @vt_Source AS vs
    )
SELECT
    ni.ts
    ,ni.next_interval AS interval
FROM NextInterval AS ni
WHERE ni.next_interval IS NOT NULL
AND ni.next_interval <> ISNULL(ni.interval,0)
ORDER BY ni.ts
0
John