sql server日期递归

时间:2013-11-25 20:43:19

标签: sql sql-server

基于另一个问题SQL Server: How can you turn a series of consecutive begin and end datetimes into a single begin-end range?

我搜索递归方式以获取停机的最后日期。 我有3个停机时间。我想知道我的服务何时可用。

Sample
    DECLARE @Downtime AS TABLE(id int, beginDT datetime, endDT datetime)
    INSERT INTO @Downtime VALUES('a','09:00','11:00')
    INSERT INTO @Downtime VALUES('b','10:00','12:00')
    INSERT INTO @Downtime VALUES('c','12:00','13:00')
    INSERT INTO @Downtime VALUES('d','15:00','16:00')


DECLARE @TimeParam AS DATETIME
SET @TimeParam ='1900-01-01 11:00:00.000'

11:00,我处于停机状态(id = 1或2,无所谓)。 我的问题是,"当服务可用时(不是关闭)?"

样本上的答案是13:00。因为我们的停机时间从9到11(id = 1),id = 2给我们11到12,id = 3显示12到13.所以,它会从9降到13。

我需要一个sql查询才能找到。一个递归,而开始/结束是在另一个结束之间。

我尝试了类似的东西,但是它的非法语法

;WITH myDates(beginDT,endDT)
AS
(
    SELECT beginDT, enddt
    FROM @Downtime D1
    WHERE @TimeParam BETWEEN begindt AND endDT

    UNION ALL

    SELECT beginDT, endDT 
    FROM @Downtime D2
    WHERE 
        (SELECT TOP 1  Max(enddt)
        FROM myDates )      
        BETWEEN begindt AND endDT
)
SELECT * FROM myDates 

更多样本

    INSERT INTO @Downtime VALUES('e','12:00','17:00') 
    INSERT INTO @Downtime VALUES('f','15:00','19:00') 
    INSERT INTO @Downtime VALUES('g','19:00','20:00') 
    INSERT INTO @Downtime VALUES('h','20:00','21:00') 
    INSERT INTO @Downtime VALUES('i','21:00','22:00') 
    INSERT INTO @Downtime VALUES('j','22:00','23:00')
    INSERT INTO @Downtime VALUES('k','23:00','23:01')
    INSERT INTO @Downtime VALUES('l','22:00','23:05')
    INSERT INTO @Downtime VALUES('m','22:00','23:06')
    INSERT INTO @Downtime VALUES('n','22:00','23:05')
    INSERT INTO @Downtime VALUES('o','22:00','23:17')
    INSERT INTO @Downtime VALUES('p','23:17','23:22')
    INSERT INTO @Downtime VALUES('q','23:22','23:23')
    INSERT INTO @Downtime VALUES('r','23:25','23:30')

停机时间应该是23:23。

1 个答案:

答案 0 :(得分:1)

我假设@DownTime中的日期列实际上不是时间,因为这意味着它们默认为1/1/1900。如果这个假设是错误的,请告诉我。

SQL Fiddle Demo

DECLARE @TimeParam AS DATETIME
SET @TimeParam ='1900-01-01 11:00:00.000'


;WITH myDates(id, begindt, endDT)
AS
(
    Select top 1 id, begindt, EndDT    
    from DownTime 
    where @TimeParam not between beginDT and endDT        

    UNION ALL

    SELECT DownTime.id, DownTime.beginDT, DownTime.endDT    
    FROM myDates D2,DownTime
    Where D2.endDT >= DownTime.beginDT
    and D2.beginDT <= DownTime.endDT    
    and DownTime.ID > D2.ID
)
Select top 1 EndDT from myDates order by endDT desc

这也假设表中的数据已经按照beginDT排序(正如您在样本数据中提供的那样)。如果不是这种情况,您可能必须对记录进行排序并将它们插入临时表,然后修改CTE以使用临时表。您可以尝试将ROW_NUMBER添加到CTE,但这对于递归CTE来说有点棘手。