Solo se me ocurrió una consulta CTE porque el problema es que puede haber una cadena de tiempos superpuestos, p. el registro 1 se superpone con el registro 2, el registro 2 con el registro 3 y así sucesivamente. Esto es difícil de resolver sin CTE o algún otro tipo de bucles, etc. Pruébelo de todos modos.
La primera parte de la consulta CTE obtiene los servicios que inician un nuevo grupo y no tienen la misma hora de inicio que algún otro servicio (necesito tener solo un registro que inicie un grupo). La segunda parte obtiene aquellos que inician un grupo, pero hay más de uno con la misma hora de inicio; nuevamente, solo necesito uno de ellos. La última parte se acumula recursivamente en el grupo inicial, tomando todos los servicios superpuestos.
Aquí está SQLFiddle con más registros agregados para demostrar diferentes tipos de tiempos superpuestos y duplicados.
No pude usar ServiceID
ya que tendría que ordenarse de la misma manera que 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