2013-01-19 38 views
2

我有StartTimes的一張桌子和EndTimes拆分INT值成行在TSQL

我想這些每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超出了此功能......但不能完成我的頭圍繞如何。

+0

您可以加入預期的一些數據結果呢? – WKordos

回答

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 

注意上面的查詢做兩個假設:

  • 您所有的開始時間 - 結束時間的組合必須是由15
  • 沒有你的開始時間的整除差異 - 結束時間對遍歷範圍寬一百15分鐘的時間(如果是這樣,你只需要使ids表更大)。

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

1

你也可以使用一個resursive 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

1
SET STATISTICS IO ON; 
GO 

DECLARE @StartTime DATETIME = '20130119 10:05:01', 
    @EndTime DATETIME = '20130119 11:05:00'; 

WITH N10(Num) -- This CTE generate all numbers (column Num) between 1 and 10 
AS (
    SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 
    UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 
), N100(Num) -- This CTE generate all numbers (column Num) between 1 and 100 
AS (
    SELECT (a.Num-1)*10 + b.Num 
    FROM N10 a CROSS JOIN N10 b 
), N10000(Num) -- This CTE generate all numbers (column Num) between 1 and 10000 
AS (
    SELECT (a.Num-1)*10 + b.Num 
    FROM N100 a CROSS JOIN N100 b 
) 
SELECT n.Num, 
     DATEADD(MINUTE, (n.Num-1)*15, @StartTime) AS MyDate 
FROM N10000 n 
WHERE /*n.Num <= (DATEDIFF(MINUTE, @StartTime, @EndTime)/15 + 1) -- If you have performance problems you could uncomment this section 
AND  */DATEADD(MINUTE, (n.Num-1)*15, @StartTime) <= @EndTime; 

結果(無邏輯讀):

Num   MyDate 
----------- ----------------------- 
1   2013-01-19 10:05:01.000 
2   2013-01-19 10:20:01.000 
3   2013-01-19 10:35:01.000 
4   2013-01-19 10:50:01.000 

(4 row(s) affected) 

(1 row(s) affected)