Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Spłaszcz/scal nakładające się przedziały czasu

Wymyśliłem tylko zapytanie CTE, ponieważ problemem może być łańcuch nakładających się czasów, np. rekord 1 pokrywa się z rekordem 2, rekord 2 z rekordem 3 i tak dalej. Jest to trudne do rozwiązania bez CTE lub innego rodzaju pętli itp. Proszę spróbować.

Pierwsza część zapytania CTE pobiera usługi, które uruchamiają nową grupę i nie mają tego samego czasu rozpoczęcia, co inne usługi (potrzebuję tylko jednego rekordu, który uruchamia grupę). Druga część obejmuje tych, którzy rozpoczynają grupę, ale jest ich więcej niż jedna z tym samym czasem rozpoczęcia - znowu potrzebuję tylko jednego z nich. Ostatnia część rekursywnie buduje się na grupie początkowej, biorąc wszystkie nakładające się usługi.

Oto SQLFiddle z większą liczbą dodanych rekordów, aby zademonstrować różne rodzaje nakładania się i duplikowania czasów.

Nie mogłem użyć ServiceID ponieważ musiałby być zamawiany w taki sam sposób jak 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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Usuń zduplikowane wiersze w SQL Server

  2. SQL Server:Jaka jest różnica między CROSS JOIN a FULL OUTER JOIN?

  3. SSMS wersja 18 – brak diagramów bazy danych

  4. Jak przestawić tabelę przestawną na rok w SQL?

  5. Spotlight Cloud Basic:najlepsze bezpłatne narzędzie do monitorowania wydajności bazy danych