我有一个包含数百万行的“服务”表.每行对应于工作人员在给定日期和时间间隔内提供的服务(每行具有唯一ID).在某些情况下,工作人员可能会在重叠的时间范围内提供服务.我需要编写一个合并重叠时间间隔的查询,并以下面显示的格式返回数据.
我尝试按StaffID和Date字段进行分组,并获得开始时间的最小值和结束时间的最大值,但这并不考虑非重叠的时间范围.我怎么能做到这一点?同样,该表包含数百万条记录,因此递归CTE方法可能会出现性能问题.提前致谢.
服务表
ID StaffID Date BeginTime EndTime
1 101 2014-01-01 08:00 09:00
2 101 2014-01-01 08:30 09:30
3 101 2014-01-01 18:00 20:30
4 101 2014-01-01 19:00 21:00
产量
StaffID Date BeginTime EndTime
101 2014-01-01 08:00 09:30
101 2014-01-01 18:00 21:00
这是另一个样本数据集,其中包含由贡献者提出的查询.
http://sqlfiddle.com/#!6/bfbdc/3
结果集中的前两行应合并为一行(06:00-08:45),但它会生成两行(06:00-08:30& 06:00-08:45)
最佳答案 我只想出了一个CTE查询,因为问题是可能存在一系列重叠时间,例如:记录1与记录2重叠,记录2与记录3重叠,依此类推.如果没有CTE或其他类型的循环等,这很难解决.无论如何,请试一试.
CTE查询的第一部分获取启动新组的服务,并且与其他服务没有相同的开始时间(我只需要一条启动组的记录).第二部分是那些开始组的人,但是有多个人有相同的开始时间 – 再次,我只需要其中一个.最后一部分递归地建立在起始组上,采用所有重叠的服务.
这是SQLFiddle,添加了更多记录以演示不同类型的重叠和重复时间.
我无法使用ServiceID,因为它必须以与BeginTime相同的方式进行排序.
;with flat as
(
select StaffID, ServiceDate, BeginTime, EndTime, BeginTime as groupid
from services S1
where not exists (select * from services S2
where S1.StaffID = S2.StaffID
and S1.ServiceDate = S2.ServiceDate
and S2.BeginTime <= S1.BeginTime and S2.EndTime <> S1.EndTime
and S2.EndTime > S1.BeginTime)
union all
select StaffID, ServiceDate, BeginTime, EndTime, BeginTime as groupid
from services S1
where exists (select * from services S2
where S1.StaffID = S2.StaffID
and S1.ServiceDate = S2.ServiceDate
and S2.BeginTime = S1.BeginTime and S2.EndTime > S1.EndTime)
and not exists (select * from services S2
where S1.StaffID = S2.StaffID
and S1.ServiceDate = S2.ServiceDate
and S2.BeginTime < S1.BeginTime
and S2.EndTime > S1.BeginTime)
union all
select S.StaffID, S.ServiceDate, S.BeginTime, S.EndTime, flat.groupid
from flat
inner join services S
on flat.StaffID = S.StaffID
and flat.ServiceDate = S.ServiceDate
and flat.EndTime > S.BeginTime
and flat.BeginTime < S.BeginTime and flat.EndTime < S.EndTime
)
select StaffID, ServiceDate, MIN(BeginTime) as begintime, MAX(EndTime) as endtime
from flat
group by StaffID, ServiceDate, groupid
order by StaffID, ServiceDate, begintime, endtime