Ich habe mir nur eine CTE-Abfrage ausgedacht, da das Problem darin besteht, dass es möglicherweise eine Kette von sich überschneidenden Zeiten gibt, z. Datensatz 1 überschneidet sich mit Datensatz 2, Datensatz 2 mit Datensatz 3 und so weiter. Dies ist ohne CTE oder andere Schleifen usw. schwer zu lösen. Bitte versuchen Sie es trotzdem.
Der erste Teil der CTE-Abfrage ruft die Dienste ab, die eine neue Gruppe starten und nicht die gleiche Startzeit wie ein anderer Dienst haben (ich brauche nur einen Datensatz, der eine Gruppe startet). Der zweite Teil bekommt diejenigen, die eine Gruppe starten, aber es gibt mehr als eine mit der gleichen Startzeit - wieder brauche ich nur eine von ihnen. Der letzte Teil baut rekursiv auf der Startgruppe auf und nimmt alle überlappenden Dienste in Anspruch.
Hier ist SQLFiddle mit weiteren Datensätzen hinzugefügt, um verschiedene Arten von Überschneidungen und doppelten Zeiten zu demonstrieren.
Ich konnte ServiceID
nicht verwenden da es genauso wie BeginTime
bestellt werden müsste .
;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