2012-11-17 272 views
1

試圖在SQL中爲以下內容編寫查詢:事件具有開始/結束日期/時間。 用戶可用於某些時間。我如何找到用戶可用於特定事件的總時間?在另一個日期範圍內總結日期範圍

實施例:

--Event-- 
eventID eventStart   eventEnd 
1  2012-10-10 15:00 2012-10-10 18:00 

--Available-- 
userID availStart   availEnd 
64  2012-10-10 10:00 2012-10-10 16:00 
64  2012-10-10 16:30 2012-10-10 16:40 
64  2012-10-10 16:55 2012-10-10 22:00 

用戶可以自由135分鐘(60分鐘從15:00-16:00,16 10分鐘:30-16:40,16 65分鐘:55- 18:00)。

有些幫助編寫SQL會非常有幫助,發現這一個棘手!

+0

@米奇小麥我可以得到事件運行,用戶可用的總時間,即'SUM(DATEDIFF(MI,availStart,availEnd))',但我確實不能工作的總時間瞭解如何統計事件時間內的可用條目(包括稍後開始/結束但僅統計事件內部的那些條目)。 – Marcus

回答

1

現在測試了它:http://sqlfiddle.com/#!3/a4e7a/2

我假定一個用戶表。性能改進的空間很大。例如通過添加一個where子句來消除不重疊的範圍。如果用一個可怕的case語句替換函數,它可能也會更快。

棘手的一點是搞清楚兩個時間段有多少重疊的算法。我總是發現它有用繪製的情況下的圖片:

Case 1 
|------| 
     |=======| 

Case 2 
|------| 
    |======| 

Case 3 
|-------| 
    |===| 

和等效的命令相反。

原來重疊是兩個結束時間的最小值減去兩個開始時間的最大值。 (如果爲負數則不重疊)。我總是必須檢查所有的情況才能重新說服自己。

-- Function that determines how many minutes of overlap there are between two timespans 
Create Function dbo.MinutesOverlap(
    @Start1 as datetime, @End1 as datetime, @Start2 as datetime, @End2 as datetime 
) Returns int As 
Begin 
    Declare 
    @MaxStart As datetime, 
    @MinEnd As datetime, 
    @Ret int = 0 

    Set @MaxStart = Case When @Start1 > @Start2 Then @Start1 Else @Start2 End 
    Set @MinEnd = Case When @End1 > @End2 Then @End2 Else @End1 End 

    If @MaxStart < @MinEnd 
    Set @Ret = DateDiff(Minute, @MaxStart, @MinEnd) 

    Return @Ret 
End 


Select 
    u.UserID, 
    e.EventID, 
    Sum(dbo.MinutesOverlap(e.eventStart, e.eventEnd, a.availStart, a.availEnd)) 
From 
    Event e 
    Cross Join 
    User u 
    Left Outer Join 
    Available a 
    On u.UserID = a.UserID 
Group By 
    u.UserID, 
    e.EventID