2013-03-19 31 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