2011-08-22 38 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正在试图通过重新命名“重塑”数字表的想法(并非源自他)。因此,讨论会在两个人使用不同的术语的地方演变,并且可能会令人困惑。数字表*可以用于计数,但这只是一个非常具体的用例,即使它是更常见的用例之一。无论如何,这只是我的看法,完全是主观的,但我想尽量减少人们可能会听到的“理货表”这个词的泛滥。 :-) –