在 SQL Server 2012 中按 7 天 windows 分组轮班数据
Grouping shift data by 7-day windows in SQL Server 2012
我想做的是计算每个员工在任何给定的 7 天内的班次和工作小时数。为了实现这一点,我需要识别和分组 'islands' 班次。请注意,这 7 天期限与日历周无关,并且这 7 天期限的开始和结束时间因员工而异。这与她过去问过的其他类似问题不同。
我有一个 table 这样的:
Person ID Start Date End Date Start time End time Hours Worked
12345 06-07-20 06-07-20 6:00 AM 7:45 AM 1.75
12345 06-07-20 06-07-20 8:15 AM 8:45 AM 0.50
12345 06-07-20 06-07-20 9:19 AM 9:43 AM 0.40
12345 08-07-20 08-07-20 12:00 AM 12:39 AM 0.65
12345 09-07-20 09-07-20 10:05 PM 11:59 PM 1.90
12345 11-07-20 11-07-20 4:39 PM 4:54 PM 0.25
12345 22-07-20 22-07-20 7:00 AM 7:30 AM 0.50
12345 23-07-20 23-07-20 1:00 PM 3:00 PM 2.00
12345 24-07-20 24-07-20 9:14 AM 9:35 AM 0.35
12345 27-07-20 27-07-20 4:00 PM 6:00 PM 2.00
12345 27-07-20 27-07-20 2:00 PM 4:00 PM 2.00
12345 28-07-20 28-07-20 9:00 AM 10:00 AM 1.00
12345 28-07-20 28-07-20 4:39 AM 4:59 AM 0.34
我想对上面的数据进行分组总结:
Person ID From To Number of shifts Number of Hours
12345 06-07-20 11-07-20 6 5.45
12345 22-07-20 28-07-20 7 8.19
请注意,员工 12345
的第一个分组从 06-07-20
开始并在 11-07-20
结束,因为这些轮班属于 06-07-20
- 13-07-20
7 -天 window.
下一天 7 天 window 是从 22-07-20
到 28-07-20
,这意味着 7 天 window 的开始日期必须是动态的并基于数据,即不是常量,这使得这是一项复杂的任务。
另请注意,一名员工可能一天工作多个班次,而且这些班次可能不是连续的。
我正在尝试将 DATEDIFF()
与 LAG()
和 LEAD()
一起使用,但无法到达我想要的位置。任何帮助将不胜感激。
我认为您需要一个递归 CTE 来解决这个问题。这个想法是枚举每个人的班次,然后迭代遍历数据集,同时跟踪周期的第一个日期——当一个周期的开始和当前日期之间有超过 7 天的时间,开始日期重置,新组开始。
with recursive
data as (select t.*, row_number() over(partition by personid order by start_date) rn from mytable t)
cte as (
select personid, start_date, start_date end_date, hours_worked, rn
from data
where rn = 1
union all
select
c.personid,
case when d.start_date > dateadd(day, 7, c.start_date) then d.start_date else c.start_date end,
d.start_date,
d.hours_worked,
d.rn
from cte c
inner join data d on d.personid = c.personid and d.rn = c.rn + 1
)
select personid, start_date, max(start_date) end_date, count(*) no_shifts, sum(hours_worked)
from cte
group by personid, start_date
这假设:
日期不会跨越多天,如示例数据所示
日期存储为 date
数据类型,时间存储为 time
我想做的是计算每个员工在任何给定的 7 天内的班次和工作小时数。为了实现这一点,我需要识别和分组 'islands' 班次。请注意,这 7 天期限与日历周无关,并且这 7 天期限的开始和结束时间因员工而异。这与她过去问过的其他类似问题不同。
我有一个 table 这样的:
Person ID Start Date End Date Start time End time Hours Worked
12345 06-07-20 06-07-20 6:00 AM 7:45 AM 1.75
12345 06-07-20 06-07-20 8:15 AM 8:45 AM 0.50
12345 06-07-20 06-07-20 9:19 AM 9:43 AM 0.40
12345 08-07-20 08-07-20 12:00 AM 12:39 AM 0.65
12345 09-07-20 09-07-20 10:05 PM 11:59 PM 1.90
12345 11-07-20 11-07-20 4:39 PM 4:54 PM 0.25
12345 22-07-20 22-07-20 7:00 AM 7:30 AM 0.50
12345 23-07-20 23-07-20 1:00 PM 3:00 PM 2.00
12345 24-07-20 24-07-20 9:14 AM 9:35 AM 0.35
12345 27-07-20 27-07-20 4:00 PM 6:00 PM 2.00
12345 27-07-20 27-07-20 2:00 PM 4:00 PM 2.00
12345 28-07-20 28-07-20 9:00 AM 10:00 AM 1.00
12345 28-07-20 28-07-20 4:39 AM 4:59 AM 0.34
我想对上面的数据进行分组总结:
Person ID From To Number of shifts Number of Hours
12345 06-07-20 11-07-20 6 5.45
12345 22-07-20 28-07-20 7 8.19
请注意,员工 12345
的第一个分组从 06-07-20
开始并在 11-07-20
结束,因为这些轮班属于 06-07-20
- 13-07-20
7 -天 window.
下一天 7 天 window 是从 22-07-20
到 28-07-20
,这意味着 7 天 window 的开始日期必须是动态的并基于数据,即不是常量,这使得这是一项复杂的任务。
另请注意,一名员工可能一天工作多个班次,而且这些班次可能不是连续的。
我正在尝试将 DATEDIFF()
与 LAG()
和 LEAD()
一起使用,但无法到达我想要的位置。任何帮助将不胜感激。
我认为您需要一个递归 CTE 来解决这个问题。这个想法是枚举每个人的班次,然后迭代遍历数据集,同时跟踪周期的第一个日期——当一个周期的开始和当前日期之间有超过 7 天的时间,开始日期重置,新组开始。
with recursive
data as (select t.*, row_number() over(partition by personid order by start_date) rn from mytable t)
cte as (
select personid, start_date, start_date end_date, hours_worked, rn
from data
where rn = 1
union all
select
c.personid,
case when d.start_date > dateadd(day, 7, c.start_date) then d.start_date else c.start_date end,
d.start_date,
d.hours_worked,
d.rn
from cte c
inner join data d on d.personid = c.personid and d.rn = c.rn + 1
)
select personid, start_date, max(start_date) end_date, count(*) no_shifts, sum(hours_worked)
from cte
group by personid, start_date
这假设:
日期不会跨越多天,如示例数据所示
日期存储为
date
数据类型,时间存储为time