我试图仅使用SQL从分组时间间隔(或句点)中选择常见的重叠时间间隔,这可能是正确的单词。
现实世界的情景是一个可以接听电话的3个以上位置的呼叫中心。职位由特定服务代表填补,他们对职位的分配随着时间的推移而变化,但这与此问题无关。我们可以假设,对于给定的位置,它总是被某人填充。
职位数量随时间缓慢变化。我试图概括解决方案,以便它可以处理任意数量的位置。
输入数据是一组调用,它们被定向到一个位置并具有开始时间和结束时间。显然,给定的位置不能与自身重叠调用(假设一次只能调用一次),但其调用可以在一次或多次调用其他位置时与时间重叠。
问题是从呼叫数据中识别所有位置在通话中的所有时间间隔,因此呼叫中心无法应答该时段内的任何新来电("所有位置忙碌& #34)
。,例如,三个职位(编号为1,2 3)
Call Position CallStartTime CallEndTime
1 1 2014-01-01 14:01 2014-01-01 14:33 <--Comprises all busy intervals 1 and 2
2 1 2014-01-01 14:45 2014-01-01 14:47
3 1 2014-01-01 14:53 2014-01-01 14:57
4 2 2014-01-01 13:01 2014-01-01 13:53
5 2 2014-01-01 13:55 2014-01-01 14:25 <--comprises all busy interval 1
6 2 2014-01-01 14:27 2014-01-01 14:29 <--comprises all busy interval 2
7 2 2014-01-01 14:35 2014-01-01 14:41
8 3 2014-01-01 14:21 2014-01-01 15:03 <--comprises all busy intervals 1 and 2
9 3 2014-01-01 16:01 2014-01-01 16:11
对于上面的测试数据,当所有位置都忙时(所有位置重叠呼叫的不同情况)有两个时间间隔:14:21-14:25和14:27-14:29。
所以期望的结果集是
AllBusyStartTime AllBusyEndTime
2014-01-01 14:21 2014-01-01 14:25
2014-01-01 14:27 2014-01-01 14:29
您看到一个呼叫可能与其他呼叫有多个重叠(例如,呼叫位置1 14:01-14:33与呼叫位置2 13:55-14:25和呼叫位置2 14:27-14重叠:29)。
当a.StartTime&lt;时间间隔时,两个时间间隔(a,b)重叠。 b.EndTime和a.EndTime&gt; = b.StartTime。
如果我能得到一组呼叫时间间隔,其中所有位置都有重叠,则相关的&#34;全部忙碌&#34;时间间隔包括来自集合的GREATEST(最近的)StartTime和最低(最旧的)EndTime。
为了更接近解决方案,我正在寻找一种通用算法来确定n个时间间隔何时相互重叠。对于间隔a,b,c选择重叠b和重叠c不是足够的限制。 A可能重叠b但b可能不会重叠c,您需要所有的间隔相互重叠。
我正在使用SQL Server进行测试。我试过在网上搜索但没有发现任何涵盖这种情况的内容(很多关于两个重叠时间间隔的简单情况的讨论)。我会分享SQL,但我仍然试图弄清楚&#34;方法&#34;,这是需要照亮的。
尽管我的测试只有SQL-Server,但我希望尽可能保持解决方案的通用性,因为它可能不会在SQL Server上实现。
答案 0 :(得分:2)
让我们随时了解同时获取同时呼叫的数量。方法是获得一个时间列表,其中+1表示呼叫开始,-1表示呼叫结束。以下给出了每个时间段的计数:
select thetime, sum(incall) over (order by thetime, call) as simultaneouscalls
from ((select CallStartTime as thetime, call, +1 as incall
from calls
) union all
(select CallEndTime, call, -1 as incall
from calls
)
) c;
接下来,您需要句点,因此请使用lead()
来结束句点,然后按同时调用的次数排序:
with c as (
select thetime, sum(incall) over (order by thetime, call) as simultaneouscalls
from ((select CallStartTime as thetime, call, +1 as incall
from calls
) union all
(select CallEndTime, call, -1 as incall
from calls
)
) c
)
select thetime, endtime, simultaneouscalls
from (select c.*, lead(thetime) over (order the thetime) as endtime
from c
) c
order by simultaneouscalls, thetime;
如果您确实只想要最大值,请将此where
子句添加到外部查询:
where simultaneouscalls = (select count(distinct position) from calls)
注意:这使用了SQL Server 2012+中可用的构造,但在早期版本中没有(因为我写的是没有版本的指示)。