这是一个很好的:假设你有一个带有开始和停止列的通话记录表作为日期时间 - 这有点像这样:
callID, start, end, caller, callee
1, 12/9/13 7:01 am, 12/9/13 7:15 am, 555-1212, 222-1616
2, 12/9/13 7:04 am, 12/9/13 7:06 am, 555-1213, 222-1516
3, 12/9/13 7:04 am, 12/9/13 7:10 am, 555-1222, 222-1646
4, 12/9/13 7:07 am, 12/9/13 7:31 am, 555-1312, 222-1674
5, 12/9/13 7:08 am, 12/9/13 7:10 am, 555-1417, 222-1655
我怎样才能找到当天的最大并发呼叫数(重叠开始和结束时间的最大呼叫数) - 以及该集的呼叫ID?
尝试找出比较多个持续时间的最佳策略。谢谢!
答案 0 :(得分:0)
这似乎是这样做的。看起来有点复杂(我不喜欢两次加入时间)但应该相对容易理解:
declare @t table (callID int not null,start datetime not null,[end] datetime not null,[caller] char(8) not null,callee char(8) not null)
insert into @t(callID, start, [end], [caller], callee) values
(1, '2013-09-12T07:01:00', '2013-09-12T07:15:00', '555-1212', '222-1616'),
(2, '2013-09-12T07:04:00', '2013-09-12T07:06:00', '555-1213', '222-1516'),
(3, '2013-09-12T07:04:00', '2013-09-12T07:10:00', '555-1222', '222-1646'),
(4, '2013-09-12T07:07:00', '2013-09-12T07:31:00', '555-1312', '222-1674'),
(5, '2013-09-12T07:08:00', '2013-09-12T07:10:00', '555-1417', '222-1655')
;With Starts as (
select Distinct start from @t
), Groups as (
select s.start,COUNT(*) Cnt
from Starts s inner join @t t on t.start <= s.start and t.[end] > s.start
group by s.start
), Ordered as (
select start,Cnt,RANK() OVER (ORDER BY Cnt desc) as rnk
from Groups
), CallGroups as (
select start,Cnt,ROW_NUMBER() OVER (ORDER BY start) as CallGroup
from Ordered
where rnk = 1
)
select CallGroup,t.*,cg.start
from CallGroups cg
inner join
@t t
on
t.start <= cg.start and t.[end] > cg.start
@t
只是您的示例数据。 Starts
CTE查找所有呼叫开始时间 - 从逻辑上讲,当一个或多个呼叫刚刚启动时,某些点达到了最大并发呼叫数。
Groups
找到每个开始时间重叠的所有呼叫。然后Ordered
和CallGroups
找到达到最大值的时间(因为数据集中可能有多个最大值,我决定找到所有这样的最大值),并分配每个最大值单独的CallGroup
值。
最后,对于最大值,我们重新选择对每个最大值都有效的所有调用:
CallGroup callID start end caller callee start
-------------------- ----------- ----------------------- ----------------------- -------- -------- -----------------------
1 1 2013-09-12 07:01:00.000 2013-09-12 07:15:00.000 555-1212 222-1616 2013-09-12 07:08:00.000
1 3 2013-09-12 07:04:00.000 2013-09-12 07:10:00.000 555-1222 222-1646 2013-09-12 07:08:00.000
1 4 2013-09-12 07:07:00.000 2013-09-12 07:31:00.000 555-1312 222-1674 2013-09-12 07:08:00.000
1 5 2013-09-12 07:08:00.000 2013-09-12 07:10:00.000 555-1417 222-1655 2013-09-12 07:08:00.000
因此,样本数据中的最大值(仅一个)发生在07:08,并且是四次调用(如果要包含计数,只需将cg.Cnt
添加到最终查询中)。如果还有另一个时间达到四次调用,我们将有8个输出行,第二组四个为CallGroup
2。
意识到我可以消除一个CTE。而不是:
, Ordered as (
select start,Cnt,RANK() OVER (ORDER BY Cnt desc) as rnk
from Groups
), CallGroups as (
select start,Cnt,ROW_NUMBER() OVER (ORDER BY start) as CallGroup
from Ordered
where rnk = 1
)
select CallGroup,t.*,cg.start
from CallGroups cg
inner join
@t t
on
t.start <= cg.start and t.[end] > cg.start
我们可以:
, CallGroups as (
select start,Cnt,RANK() OVER (ORDER BY Cnt desc) as rnk,
ROW_NUMBER() OVER (PARTITION BY Cnt ORDER BY start) as CallGroup
from Groups
)
select CallGroup,t.*,cg.start
from CallGroups cg
inner join
@t t
on
t.start <= cg.start and t.[end] > cg.start
where cg.rnk = 1
我一直在误以为在我们分配连续的RANK()
值之前我们需要CallGroup
的结果,但事实并非如此。