2

StartTimes と EndTimes のテーブルがあります

これらを各開始時間と終了時間の間で 15 分ごとに 1 行に分割したいと考えています。

何かのようなもの

SELECT StartTime, DATEDIFF(mi, StartTime, EndTime) / 15 AS Offset FROM myTable
CROSS APPLY
-- put something in here to split each row into (EndTime - StartTime) / 15 rows

これにはSQL OVER関数を使用できると思います...しかし、その方法について頭を悩ませることはできません。

4

2 に答える 2

1

存在しない行を生成する必要がある状況では、1、2、3などの番号が付けられた行の束を含む番号のテーブルを作成すると便利です。たとえば、これによりテーブルが作成されます。 0から99までの数字の:

create table ids ( id int )

declare @id int
set @id = 0
while @id < 100
begin
    insert ids values (@id)
    set @id = @id + 1
end

次に、この数値のテーブルに基づいて、元のテーブルと結合するのと同じくらい簡単で、に基づく制限idは、生成される15分の期間の数よりも少なくなります。

select
  DATEADD(mi, id * 15, StartTime) AS StartTime,
  DATEADD(mi, (id + 1) * 15, StartTime) AS EndTime
from
  MyTable T
join
  ids I on I.id < DATEDIFF(mi, StartTime, EndTime) / 15

上記のクエリは2つの仮定をしていることに注意してください。

  • すべてのStartTimeとEndTimeの組み合わせには、15で正確に割り切れる違いがあります。
  • StartTimeとEndTimeのペアはいずれも、15分の期間が100を超える範囲を通過しません(その場合は、idsテーブルを大きくする必要があります)。

デモ:http ://www.sqlfiddle.com/#!6 / 595a9

于 2013-01-19T02:11:34.573 に答える
1

補助テーブルの作成を避けるために、再帰的な CTE を使用することもできます。

WITH "CTE"
AS
(
  SELECT "id", "starttime" FROM "data"
  UNION ALL
  SELECT "id", DATEADD( MINUTE, 15, "starttime" )
  FROM "CTE"
  WHERE "starttime" < ( SELECT "endtime" FROM "data" AS D2 WHERE D2."id" = CTE."id" )
)
SELECT * FROM "CTE" 
ORDER BY "ID"

SQL-Fiddle-Demoを参照してください。

上記のクエリでは、データ テーブルの開始時間と終了時間の組み合わせの違いが 15 で割り切れると想定しています。

正確に 15 で割り切れない日時で動作するようにクエリを編集しました。選択した 15 分の間隔が最後に計算された間隔に収まらない場合、拒否されます。

WITH "CTE"
AS
(
  SELECT "id", "starttime" FROM "data"
  UNION ALL
  SELECT "id", DATEADD( MINUTE, 15, "starttime" )
  FROM "CTE"
  WHERE "starttime" <= ( SELECT DATEADD( MINUTE, -15, "endtime" ) FROM "data" AS D2 WHERE D2."id" = CTE."id" )
)
SELECT * FROM "CTE" 
ORDER BY "ID"

結果で ( fiddle-demo で) 拒否された最後のタイムスタンプを取得したい場合は、 にid 2, timestamp "12:00:00"変更<=するだけ<です。これは、ハーフ オープン インターバルで作業している場合にも関係します。

編集された SQL-Fiddle-Demoを参照してください

于 2013-01-19T10:11:09.010 に答える