汇总和细分重叠日期范围

时间:2021-04-13 03:57:36

标签: sql sql-server tsql

我们的 HR 系统指定了员工分配,这些分配可以是并发的。我们的排班系统只允许一个人进行一项摘要分配。因此,我需要对 HR 记录进行预处理,以便排班可以确定工人在特定日期的预期工作班次。

看看有两个任务的工人 A,第一个是四分之一班,第二个是半班,但在他们工作 0.75 班的中间重叠。

Person StartDate EndDate Shifts
   A   01/01/21  04/01/21   .25
   A   03/01/21  06/01/21   .5

      01---02---03---04---05---06---07
Rec 1 |------------------|
Rec 2 |        |===================|
Total |  0.25  |   0.75  |   0.5   |

所需的输出。

Person StartDate EndDate  ShiftCount
   A   01/01/21  02/01/21   0.25
   A   03/01/21  04/01/21   0.75
   A   05/01/21  06/01/21   0.5

给定这些数据,我们如何对数据进行汇总和分割?我找到了一个关于 MySQL 的确切问题,但版本太早,建议使用代码。我还找到了 Postgres 解决方案,但我们没有范围。

select * from (
values 
('A','01/01/21','04/01/21',0.25),
('A','03/01/21','05/01/21',0.5)
) AS Data (Person,StartDate,EndDate,Shifts);

1 个答案:

答案 0 :(得分:3)

对我来说它看起来像一个缺口和岛屿。

如果有帮助,cte1 用于通过临时计数表扩展日期范围。然后 cte2 用于创建间隙和岛屿。最终的结果就是聚合的小问题。

示例

Set Dateformat DMY

Declare @YourTable table (Person varchar(50),StartDate Date,EndDate date,Shifts decimal(10,2))
Insert Into @YourTable values
 ('A','01/01/21','04/01/21',0.25)
,('A','03/01/21','05/01/21',0.5)


;with cte1 as (
Select [Person]
      ,[d] = dateadd(DAY,N,StartDate)
      ,Shifts = sum(Shifts)
 From  @YourTable A
 Join  (
        Select Top 1000 N=-1+Row_Number() Over (Order By (Select Null))
         From  master..spt_values n1,master..spt_values n2
       ) B on N <= datediff(DAY,[StartDate],[EndDate])
 Group By Person,dateadd(DAY,N,StartDate)
 ), cte2 as (
 Select *
      ,Grp    = datediff(day,'1900-01-01',d)-row_number() over (partition by Person,Shifts Order by d)
  From cte1
)
Select Person
      ,StartDate = min(d)
      ,EndDate   = max(d)
      ,Shifts    = max(Shifts)
  From cte2
  Group By Person,Grp

退货

Person  StartDate   EndDate     Shifts
A       2021-01-01  2021-01-02  0.25
A       2021-01-03  2021-01-04  0.75
A       2021-01-05  2021-01-05  0.50