合并时间表行,开始时间和结束时间之间没有间隔

问题描述

我正在开发一个时间表系统,在该系统中,员工每天都在从事各种工作。我需要进行某种查询,以返回时间的合并版本,这样,如果一名员工一整天都在工作之间没有任何休息,那么我当天只能得到一行。但是,如果在一行的结束时间和下一行的开始时间之间存在间隙,则应该将其作为单独的一行返回。我还需要休息时间和总计时间。

我希望这有意义吗?我可能可以用光标之类的东西来做,但这并不是最优雅的方法

DECLARE @Times TABLE (StartTime DATETIME,EndTime DATETIME,BreakHours DECIMAL(8,2),TotalHours DECIMAL(8,2))
INSERT INTO @Times (StartTime,EndTime,BreakHours,TotalHours)
VALUES ('2020-08-24 07:00','2020-08-24 08:30',0.00,1.50),('2020-08-24 08:30','2020-08-24 12:00',0.50,3.00),('2020-08-24 12:00','2020-08-24 16:00',4.00),('2020-08-24 16:00','2020-08-24 17:30',('2020-08-25 07:00','2020-08-25 08:30',('2020-08-25 08:30','2020-08-25 11:45',2.75),('2020-08-25 12:00','2020-08-25 16:00',('2020-08-25 16:00','2020-08-25 17:45',1.75),('2020-08-25 23:00','2020-08-26 05:00',5.50)

这是我想要看到的结果集...

StartTime           EndTime             BreakHours  TotalHours
2020-08-24 07:00    2020-08-24 17:30    0.50        10.00
2020-08-25 07:00    2020-08-25 11:45    0.50        4.25
2020-08-25 12:00    2020-08-25 17:45    0.00        5.75
2020-08-25 23:00    2020-08-26 05:00    0.50        5.50

解决方法

这是一个空白和孤岛的问题。一种方法是使用lag()检索“上一个”结束日期,并使用窗口sum(),每当满足间隔时,窗口就会增加。这定义了相邻行的组,然后可以对其进行汇总:

select 
    min(starttime) starttime,max(endtime) endtime,sum(breakhours) breakhours,sum(totalhours) totalhours
from (
    select t.*,sum(case when starttime = lag_endtime then 0 else 1 end) over(order by starttime) grp
    from (
        select t.*,lag(endtime) over(order by starttime) lag_endtime
        from mytable t
    ) t
) t
group by grp

您的数据似乎缺少标识员工的列。如果有一个,通常将其作为partition添加到窗口函数的over()子句以及外部查询的group by子句中。