SQL 服务器:根据开始日期和结束日期将一行分成几行

SQL Server : splitting a row into several rows based off it's start and end date

SQL 服务器:我有一个缺勤 table 每个员工缺勤都有一个记录,其中有缺勤的开始和结束日期。例如

Person Ref    Start Date     End Date
---------------------------------------
1234          01/01/2021     05/01/2021

我想根据日期范围将这一行分成几行,这样一来,每一行都代表缺席,而不是一行代表缺席,就像这样:

Person Ref    Start Date   End Date
------------------------------------
1234          01/01/2021   01/01/2021
1234          02/01/2021   02/01/2021
1234          03/01/2021   03/01/2021
1234          04/01/2021   04/01/2021
1234          05/01/2021   05/01/2021

是否可以根据日期范围将行拆分为单独的行,以便缺席的每一天都有自己的行?提前致谢。

可能值得注意的是,这是源数据,将被转换为临时区域。

更新: 我还有一个小问题,你能帮忙吗?在我当前的 table 中,还有一列显示因缺勤而丢失的轮班次数以及人员参考、开始和结束日期。目前,将记录分成几行代表每一天而不是一个时间范围意味着丢失的班次数列是重复的。例如在旧的 table 中,如果某人休假 5 天并损失 3 个班次,在新的 table 中将有 3 行 - 每天一行 - 并且每天显示为损失 3 个班次。有办法拆分吗?

为了更好地解释这一点,table 过去看起来像这样:

Person Ref    Start Date   End Date    Shifts Lost
--------------------------------------------------
1234          01/01/2021   05/01/2021  3    

现在看起来像这样(由于拆分我们已经完成了)

Person Ref    Start Date   End Date    Shifts Lost
--------------------------------------------------
1234          01/01/2021   01/01/2021  3    
1234          02/01/2021   02/01/2021  3
1234          03/01/2021   03/01/2021  3
1234          04/01/2021   04/01/2021  3
1234          05/01/2021   05/01/2021  3

有没有办法拆分行之间丢失的 3 个班次的计数?由于班次模式,缺勤 5 天的人不一定会错过 5 个班次,在这种情况下他们会错过 3 个班次。有没有办法让它像:

Person Ref    Start Date   End Date    Shifts Lost
--------------------------------------------------
1234          01/01/2021   01/01/2021  1    
1234          02/01/2021   02/01/2021  1
1234          03/01/2021   03/01/2021  1
1234          04/01/2021   04/01/2021  0
1234          05/01/2021   05/01/2021  0

谢谢

如果您没有日历 Table(强烈推荐),您可以使用临时计数 table 配合简单的 JOIN。

你可能注意到Top 1000,这个可以调整到更合理的水平。

示例或dbFiddle

Select [Person Ref]
      ,[Start Date] = dateadd(DAY,N,[Start Date])
      ,[End Date]   = dateadd(DAY,N,[Start Date])
 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,[Start Date],[End Date])

Returns

Person Ref  Start Date  End Date
1234        2021-01-01  2021-01-01
1234        2021-01-02  2021-01-02
1234        2021-01-03  2021-01-03
1234        2021-01-04  2021-01-04
1234        2021-01-05  2021-01-05

更新 --- 班次丢失

Select [Person Ref]
      ,[Start Date] = dateadd(DAY,N,[Start Date])
      ,[End Date]   = dateadd(DAY,N,[Start Date])
      ,[Shifts Lost]= case when N<[Shifts Lost] then 1 else 0 end
 From  YourTable A
 Join  (
        Select Top 10000 N=-1+Row_Number() Over (Order By (Select Null))
         From  master..spt_values n1,master..spt_values n2
       ) B on N <= datediff(DAY,[Start Date],[End Date])

结果

Person Ref  Start Date  End Date    Shifts Lost
1234        2021-01-01  2021-01-01  1
1234        2021-01-02  2021-01-02  1
1234        2021-01-03  2021-01-03  1
1234        2021-01-04  2021-01-04  0
1234        2021-01-05  2021-01-05  0