2014-12-19 23 views
1
新的一天

转变的开始日期我有一个包含一些转变信息的雇员(S)查询时间序列,更新每一行与重叠到

+-------+------------+------------------+------------+------------------+------------+ 
| empid | StartDate | StartTime  | EndDate |  EndTime  | ShiftDate | 
+-------+------------+------------------+------------+------------------+------------+ 
| 391 | 2014-12-16 | 20:00:00.0000000 | 2014-12-16 | 22:00:00.0000000 | ?   | 
| 391 | 2014-12-16 | 22:00:00.0000000 | 2014-12-16 | 22:15:00.0000000 | ?   | 
| 391 | 2014-12-16 | 22:15:00.0000000 | 2014-12-17 | 00:00:00.0000000 | ?   | 
| 391 | 2014-12-17 | 00:00:00.0000000 | 2014-12-17 | 00:45:00.0000000 | ?   | 
| 391 | 2014-12-17 | 00:45:00.0000000 | 2014-12-17 | 02:30:00.0000000 | ?   | 
| 391 | 2014-12-17 | 02:30:00.0000000 | 2014-12-17 | 02:45:00.0000000 | ?   | 
| 391 | 2014-12-17 | 02:45:00.0000000 | 2014-12-17 | 04:30:00.0000000 | ?   | 
+-------+------------+------------------+------------+------------------+------------+ 
| 391 | 2014-12-17 | 20:00:00.0000000 | 2014-12-17 | 21:45:00.0000000 | ?   | 
| 391 | 2014-12-17 | 21:45:00.0000000 | 2014-12-17 | 22:00:00.0000000 | ?   | 
| 391 | 2014-12-17 | 22:00:00.0000000 | 2014-12-18 | 00:00:00.0000000 | ?   | 
| 391 | 2014-12-18 | 00:00:00.0000000 | 2014-12-18 | 00:45:00.0000000 | ?   | 
| 391 | 2014-12-18 | 00:45:00.0000000 | 2014-12-18 | 02:30:00.0000000 | ?   | 
| 391 | 2014-12-18 | 02:30:00.0000000 | 2014-12-18 | 02:45:00.0000000 | ?   | 
| 391 | 2014-12-18 | 02:45:00.0000000 | 2014-12-18 | 04:30:00.0000000 | ?   | 
+-------+------------+------------------+------------+------------------+------------+ 

表我需要更新ShiftDate列与这个班次的StartDate。所以下面是2个不同的班次,每个班次超过2天。第一班ShiftDate每行应该是2014-12-16,第二班,每行的ShiftDate应该是2014-12-17。

预期结果:

+-------+------------+------------------+------------+------------------+------------+ 
| empid | StartDate | StartTime  | EndDate |  EndTime  | ShiftDate | 
+-------+------------+------------------+------------+------------------+------------+ 
| 391 | 2014-12-16 | 20:00:00.0000000 | 2014-12-16 | 22:00:00.0000000 | 2014-12-16 | 
| 391 | 2014-12-16 | 22:00:00.0000000 | 2014-12-16 | 22:15:00.0000000 | 2014-12-16 | 
| 391 | 2014-12-16 | 22:15:00.0000000 | 2014-12-17 | 00:00:00.0000000 | 2014-12-16 | 
| 391 | 2014-12-17 | 00:00:00.0000000 | 2014-12-17 | 00:45:00.0000000 | 2014-12-16 | 
| 391 | 2014-12-17 | 00:45:00.0000000 | 2014-12-17 | 02:30:00.0000000 | 2014-12-16 | 
| 391 | 2014-12-17 | 02:30:00.0000000 | 2014-12-17 | 02:45:00.0000000 | 2014-12-16 | 
| 391 | 2014-12-17 | 02:45:00.0000000 | 2014-12-17 | 04:30:00.0000000 | 2014-12-16 | 
+-------+------------+------------------+------------+------------------+------------+ 
| 391 | 2014-12-17 | 20:00:00.0000000 | 2014-12-17 | 21:45:00.0000000 | 2014-12-17 | 
| 391 | 2014-12-17 | 21:45:00.0000000 | 2014-12-17 | 22:00:00.0000000 | 2014-12-17 | 
| 391 | 2014-12-17 | 22:00:00.0000000 | 2014-12-18 | 00:00:00.0000000 | 2014-12-17 | 
| 391 | 2014-12-18 | 00:00:00.0000000 | 2014-12-18 | 00:45:00.0000000 | 2014-12-17 | 
| 391 | 2014-12-18 | 00:45:00.0000000 | 2014-12-18 | 02:30:00.0000000 | 2014-12-17 | 
| 391 | 2014-12-18 | 02:30:00.0000000 | 2014-12-18 | 02:45:00.0000000 | 2014-12-17 | 
| 391 | 2014-12-18 | 02:45:00.0000000 | 2014-12-18 | 04:30:00.0000000 | 2014-12-17 | 

+ ------- + ------------ + -------------- ---- + ------------ + ------------------ + ------------ +

我无法处理从给定行中确定移位日期的方法。当这是一个新班次时,班次开始时间将不会与班次的前一个结束时间相同。

我与SQL 2008 R2

任何建议的工作让我朝着正确的方向将是巨大的!

+1

可以更新与预期输出 – 2014-12-19 04:09:11

+0

增加的预期结果的问题,也许是一个更好的列名应的被ShiftStartDate – kirkdmo 2014-12-19 04:14:48

+0

我看不出你如何能做到这一点 - 你怎么知道,这两个块是一除了通过检查以外的其他转变? – Rikalous 2014-12-19 09:35:14

回答

1

使用递归CTE:

;WITH 
    CTE1 AS 
    (
     SELECT empid, StartDate, StartTime, EndDate, EndTime, 
       ROW_NUMBER() OVER (PARTITION BY empid ORDER BY StartDate, StartTime) AS RowNumber 
     FROM EmployeeShift 
    ), 
    CTE2 AS (
     SELECT empid, StartDate, StartTime, EndDate, EndTime, 
       StartDate AS ShiftDate, 
       RowNumber 
     FROM CTE1 
     WHERE RowNumber = 1 

     UNION ALL 

     SELECT c1.empid, c1.StartDate, c1.StartTime, c1.EndDate, c1.EndTime, 
       CASE 
        WHEN c1.StartDate = c2.EndDate AND c1.StartTime = c2.EndTime THEN c2.ShiftDate 
        ELSE c1.StartDate 
       END AS ShiftDate, 
       c1.RowNumber 
     FROM CTE1 c1 
     INNER JOIN CTE2 c2 ON c1.empid = c2.empid AND c1.RowNumber = c2.RowNumber + 1 
    ) 

SELECT * FROM CTE2 
OPTION (MAXRECURSION 0) 

一个评注者要求其内部所以这里有云:

  1. 每班条目编号为1,2,3,...,N各员工,并根据其开始和结束日期进行排序。这是CTE1
  2. 对于第一个班次条目,ShiftDate与其StartDate相同。这是CTE2的前半部分。
  3. 从第一个班次条目开始,它递归地经历员工的下一个条目。如果下一个条目的开始时间与先前条目的结束时间相同,则继续之前的ShiftDate。否则,它将ShiftDate设置为当前班次的StartDate
+0

这是正确的解决方案,如果@ZoffDino更详细地描述它的内部组件,它会在更短的时间内变得难以置信。 – Serg 2014-12-19 15:48:39

+0

太棒了!奇迹般有效! – kirkdmo 2014-12-19 16:25:21