2011-08-22 50 views
13

我正在試圖生成一個包含一系列日期時間的表。SQL Server 2008生成一系列日期時間

我有指定的開始日期時間和結束日期時間(結束日期時間是序列結束),我添加了一個時間間隔〜(這可以變化)到開始日期時間,以秒爲單位,這給了我結束日期時間。

下一個序列使用結束日期時間作爲其起始值,並以秒爲單位添加時間間隔。爲了演示我需要的輸出。是否有一個快速的方法來創建這樣一個表,除了使用大量的插入到命令?我真的難倒

StartTime    Endtime     Duration 
2011-07-20 11:00:33  2011-07-20 11:09:47  554 
2011-07-20 11:09:47  2011-07-20 11:19:01  554 

    declare @StartTime datetime = '2011-07-20 11:00:33', 
    @EndTime datetime = '2011-07-20 15:37:34' 
    @Interval int = 554 -- this can be changed. 

    insert into tmp_IRange 
    values('2011-07-20 11:00:33', DATEADD(SECONDS, @Duration, 2011-07-20 11:00:33)) 

這變得非常乏味..尤其是當結束日期時間2011-07-20 15:37:34 有很多INSERT語句,使:(

+2

你沒有真正展示你的輸出。你能展示你真正想要的前三和後三行嗎? –

+1

請注意,基於遞歸CTE的答案有32767個遞歸級別的限制。 (請參閱MAXRECURSION文檔。) – HABO

+2

@ user92546 - 情況並非如此。 MAXRECURSION 0'無限制。 –

回答

4

這應該讓你開始。你可以把它適應您的特定需求。隨着書寫的,就會產生每分鐘的增量與當前日起&時間一排。

DECLARE @BaseDate DateTime = GETDATE(); 

WITH DateTable (DateValue) AS (
    SELECT @BaseDate DateValue 
    UNION ALL 
    SELECT DATEADD(Minute, 1, DateValue) DateValue 
    FROM DateTable 
) 
SELECT * 
FROM DateTable 
WHERE DateValue < DATEADD(Day, 1, GETDATE()) 
OPTION (MAXRECURSION 0); 
+0

它增加1秒,對吧? – JNK

+0

@JNK:是的,編輯了描述和增量。事實上,查詢會運行很長一段時間! – Yuck

+0

那麼你只有一個日期時間變量,而OP有兩個日期時間變量和一個時間間隔。爲什麼您的解決方案中沒有任何關於時間間隔(554秒)和結束日期(您假設整個一天爲1分鐘的時間間隔)? –

16

使用遞歸CTE

declare @StartTime datetime = '2011-07-20 11:00:33', 
    @EndTime datetime = '2011-07-20 15:37:34', 
    @Interval int = 554 -- this can be changed. 

;WITH cSequence AS 
(
    SELECT 
     @StartTime AS StartRange, 
     DATEADD(SECOND, @Interval, @StartTime) AS EndRange 
    UNION ALL 
    SELECT 
     EndRange, 
     DATEADD(SECOND, @Interval, EndRange) 
    FROM cSequence 
    WHERE DATEADD(SECOND, @Interval, EndRange) < @EndTime 
) 
/* insert into tmp_IRange */ 
SELECT * FROM cSequence OPTION (MAXRECURSION 0); 
+0

是在此查詢中使用的時間間隔,在此查詢中似乎存在未聲明的變量持續時間。 – jrara

+0

@jrara:謝謝,修正 – gbn

+0

作品感謝 – mouse

5

這人會給出個人的範圍,但是會忽略你的實際結束時間(因爲它是在最後的有效範圍< @interval):

;WITH x AS 
(
    SELECT TOP (DATEDIFF(SECOND, @StartTime, @EndTime)/@Interval) 
     rn = ROW_NUMBER() OVER (ORDER BY [object_id]) 
    FROM sys.objects 
) 
-- INSERT INTO dbo.tmp_IRange 
SELECT DATEADD(SECOND, @Interval * (rn-1), @StartTime), 
    DATEADD(SECOND, @Interval * rn, @StartTime) 
FROM x; 
+0

*'下一個序列使用結束日期時間作爲其起始值'*,這意味着開始時間不是固定值。 –

+0

謝謝@Andriy,錯過了;刪除第一個答案。 –

0

希望這幫助...

declare @StartTime datetime = '2011-07-20 11:00:33', 
@EndTime datetime = '2011-07-20 11:00:33', 
@Interval int = 554, 

@LimitTime datetime = '2011-07-20 15:37:34' 

WHILE @EndTime < @LimitTime 
BEGIN 
SELECT @EndTime = DATEADD(S, @Interval, @StartTime) 

SELECT @StartTime, @EndTime 
--INSERT INTO tmp_IRange VALUES(@StartTime, @EndTime) 

SELECT @StartTime = @EndTime 

END 
0

請試試這個代碼:

create table #T (date_begin datetime, date_end datetime)  

declare @StartTime datetime = '2011-07-20 11:00:33', 
    @EndTime datetime = '2011-07-20 15:37:34', 
    @Interval int = 554 -- this can be changed. 

while DATEADD(ss,@Interval,@StartTime)<[email protected] 
begin 
    insert #T 
    select @StartTime, DATEADD(ss,@Interval,@StartTime) 

    set @StartTime = DATEADD(ss,@Interval,@StartTime) 
end 


select * from #T 
3

下面是另一種非遞歸的基於集合的解決方案,它使用稱爲master..spt_values系統表:

DECLARE 
    @StartTime datetime = '2011-07-20 11:00:33', 
    @EndTime datetime = '2011-07-20 15:37:34', 
    @Interval int = 554; 
SELECT 
    StartTime = DATEADD(SECOND, (number - 1) * @Interval, @StartTime), 
    EndTime = DATEADD(SECOND, (number - 0) * @Interval, @StartTime), 
    Duration = @Interval 
FROM master..spt_values 
WHERE type = 'P' 
    AND number BETWEEN 1 AND DATEDIFF(SECOND, @StartTime, @Endtime)/@Interval 

UNION ALL 

SELECT 
    DATEADD(SECOND, -Duration, EndTime), 
    EndTime, 
    Duration 
FROM (
    SELECT 
    EndTime = @EndTime, 
    Duration = DATEDIFF(SECOND, @StartTime, @Endtime) % @Interval 
) s 
WHERE Duration > 0 

第一SELECT產生行組由指定長度的短的時間間隔位於指定範圍內的的。如有必要,第二個SELECT會在第一個SELECT的最後時間間隔的結束時間和指定的結束時間之間添加一個時間間隔。

這裏特別使用的master..spt_values的子集(可用於許多類似的情況)提供了一個0到2047之間的數字列表。這意味着您無法將該解決方案與該表一起使用如果最初的時間間隔將被分割成2047個較短的時間間隔。然後你應該想想像你自己的number table

+0

+1,但請將它稱爲數字或數字表格,而不是統計表格。它是一個數字表格,而不是一個和數表格。 :-) –

+0

沒問題!我認爲這兩個術語是完全可以互換的。雖然我承認,但我不能完全理解* tally *這個詞的含義的所有細微之處(因此,我應該在我以前的術語* tally表*中更謹慎)。非常感謝您的通知! –

+1

Jeff Moden正在試圖通過重新命名「重塑」數字表的想法(並非源自他)。因此,討論會在兩個人使用不同的術語的地方演變,並且可能會令人困惑。數字表*可以用於計數,但這只是一個非常具體的用例,即使它是更常見的用例之一。無論如何,這只是我的看法,完全是主觀的,但我想盡量減少人們可能會聽到的「理貨表」這個詞的泛濫。 :-) –