在SQL中将Int值拆分为行

时间:2013-01-19 01:54:47

标签: sql-server tsql

我有一张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函数......但是无法解决这个问题。

2 个答案:

答案 0 :(得分: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

请注意,上述查询有两个假设:

  • 所有StartTime - EndTime组合的差异都可以被15整除。
  • 您的所有StartTime - EndTime对都不会超过一百个15分钟的时间段(如果是这样,您只需要使ids表更大)。

演示:http://www.sqlfiddle.com/#!6/595a9

答案 1 :(得分:1)

您也可以使用resurive 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"

如果您想在结果中拒绝最后一个时间戳(在小提琴演示id 2, timestamp "12:00:00"中),只需将<=更改为<即可。如果您使用半开放间隔工作,这也是相关的。

请参阅edited SQL-Fiddle-Demo