2013-11-25 98 views
1

。 我有3個停機時間鏈接。我想知道我的服務何時可用。的SQL Server日期遞歸

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。

+0

爲什麼不編寫代碼而不是用SQL努力工作呢?幾行代碼可以以更容易,也許沒有錯誤的方式來實現 – nrathaus

+0

我知道,但是它的速度較慢,主要是如果我有很多停機時間。 – forX

+0

我搜索sql查詢的方式,我可以在代碼上執行,但它在經常調用的網頁上。 – forX

回答

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會有點棘手。

+0

您的權利,停機時間是一個完整的日期。只是在時間上看起來更容易。 – forX

+0

你的回答是錯誤的。認爲你想知道什麼時候系統會關閉。 – forX

+0

對不起,@forX。我最初的解決方案是基於您最初提供的有限樣本數據。我已經使用遞歸CTE更新了我的解決方案,該解決方案基於提供的假設或兩個假設來完成工作。 – JMK