合并时间表行,开始时间和结束时间之间没有间隔
Merge timesheet rows with no gap between start and finish times
我正在开发一个时间表系统,让员工全天从事各种工作。我需要做某种查询,return 是时间的合并版本,这样如果一名员工工作一整天而工作之间没有任何休息,那么我只得到那天的一行。但是,如果一行的结束时间和下一行的开始时间之间存在差距,那么这应该 return 作为单独的一行。我还需要休息时间和总小时数。
我希望这是有道理的?我可能可以用光标或其他东西来完成,但这不是最优雅的方法。
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',0.00,4.00)
,('2020-08-24 16:00','2020-08-24 17:30',0.00,1.50)
,('2020-08-25 07:00','2020-08-25 08:30',0.00,1.50)
,('2020-08-25 08:30','2020-08-25 11:45',0.50,2.75)
,('2020-08-25 12:00','2020-08-25 16:00',0.00,4.00)
,('2020-08-25 16:00','2020-08-25 17:45',0.00,1.75)
,('2020-08-25 23:00','2020-08-26 05:00',0.50,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()
来检索“先前”的结束日期,并使用 window 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
添加到 window 函数的 over()
子句,以及外部查询的 group by
子句。
我正在开发一个时间表系统,让员工全天从事各种工作。我需要做某种查询,return 是时间的合并版本,这样如果一名员工工作一整天而工作之间没有任何休息,那么我只得到那天的一行。但是,如果一行的结束时间和下一行的开始时间之间存在差距,那么这应该 return 作为单独的一行。我还需要休息时间和总小时数。
我希望这是有道理的?我可能可以用光标或其他东西来完成,但这不是最优雅的方法。
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',0.00,4.00)
,('2020-08-24 16:00','2020-08-24 17:30',0.00,1.50)
,('2020-08-25 07:00','2020-08-25 08:30',0.00,1.50)
,('2020-08-25 08:30','2020-08-25 11:45',0.50,2.75)
,('2020-08-25 12:00','2020-08-25 16:00',0.00,4.00)
,('2020-08-25 16:00','2020-08-25 17:45',0.00,1.75)
,('2020-08-25 23:00','2020-08-26 05:00',0.50,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()
来检索“先前”的结束日期,并使用 window 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
添加到 window 函数的 over()
子句,以及外部查询的 group by
子句。