2013-03-19 33 views
3

我正在使用MS SQL Server 2005,並且遇到以下問題。我有一個電話記錄,需要分析一段時間的線路利用率。我會嘗試通過省略細節來簡化任務,並只詢問我遇到的問題。 假設呼叫記錄在列表中:呼叫開始的日期和時間,呼叫持續時間(分鐘)和使用的行號。我需要計算,在每個特定時刻(每分鐘)有多少條線路忙碌。事實上,我最終會通過做一些聚合來使用更長的時間段(15分鐘,半小時等),但我不會有任何問題。根據活動開始和持續時間對活動項目進行計數

所以示例源表(3線),可以有以下內容:

StartDateTime, Duration, LineNr 
2013-01-01 10:00:00, 5, 1 
2013-01-01 10:01:00, 6, 2 
2013-01-01 10:03:00, 3, 3 
2013-01-01 10:08:00, 2, 1 
2013-01-01 10:09:00, 3, 2 
2013-01-01 10:11:00, 1, 1 

結果表從查詢返回應如下:

Period, BusyLineCount 
... 
2013-01-01 09:58:00, 0 
2013-01-01 09:59:00, 0 
2013-01-01 10:00:00, 1 
2013-01-01 10:01:00, 2 
2013-01-01 10:02:00, 2 
2013-01-01 10:03:00, 3 
2013-01-01 10:04:00, 3 
2013-01-01 10:05:00, 2 
2013-01-01 10:06:00, 1 
2013-01-01 10:07:00, 0 
2013-01-01 10:08:00, 1 
2013-01-01 10:09:00, 2 
2013-01-01 10:10:00, 1 
2013-01-01 10:11:00, 2 
2013-01-01 10:12:00, 0 
2013-01-01 10:13:00, 0 
... 

如何可以完成這個?

P.S.這是我第一次發佈的問題,英文不是我的母語,所以請不要介意我做錯了什麼。在此先感謝您的幫助。

回答

3

這是一種使用遞歸CTE的方法。這可能會在很短的時間內表現良好,但您需要用較大的測試。

DECLARE @Start DATETIME, @End DATETIME 
SET @Start = '20130101 09:58:00' 
SET @End = '20130101 10:15:00' 

;WITH TimePeriods AS 
(
    SELECT @Start Period 
    UNION ALL 
    SELECT DATEADD(MINUTE,1,Period) 
    FROM TimePeriods 
    WHERE DATEADD(MINUTE,1,Period) <= @End 
), LineUsage AS (
    SELECT StartDateTime, Duration, LineNr 
    FROM YourTable 
    UNION ALL 
    SELECT DATEADD(MINUTE,1,StartDateTime), Duration-1, LineNr 
    FROM LineUsage 
    WHERE Duration-1 > 0 
) 
SELECT A.Period, COUNT(DISTINCT B.LineNr) BusyLineCount 
FROM TimePeriods A 
LEFT JOIN LineUsage B 
    ON A.Period = B.StartDateTime 
GROUP BY A.Period 
ORDER BY A.Period 
OPTION(MAXRECURSION 0) 

Here is a sql fiddle與此現場演示。

+0

謝謝拉瑪克!偉大的技術。我從來不知道遞歸cte,你絕對爲我找到了一個寶藏。 Btw。與此同時,我發現了一種沒有CTE的方法(用預填充週期表替換第一個CTE,用JOIN替換第二個CTE),我將嘗試填充一個巨大的測試源表並測量兩種方式的性能。 – Kyrill 2013-03-20 05:34:52

+0

@Killill恭喜有另一種解決方案,並有意將性能與較大的數據集進行比較。您可能想爲未來的讀者發佈自己的答案:-) – Lamak 2013-03-20 12:32:45