如何在存储过程的选择中将记录作为中断时间插入

Rog*_*ira 2 sql t-sql sql-server sql-server-2012

有了这个表Sql Server 2012,我需要返回插入正确位置的中断时间.

如有必要,我可以使用临时表.

休息:这是时间的差异,所以我需要一个代表差距的新记录.

表:

???????????????????????????????????????????????????????
?     Start      ?      End       ? Duration ?  Type  ?
???????????????????????????????????????????????????????
? 1/06/2015 1:00 ? 1/06/2015 1:30 ? 0:30     ? Logged ?
? 1/06/2015 2:00 ? 1/06/2015 3:00 ? 1:00     ? Logged ?
? 1/06/2015 3:20 ? 1/06/2015 4:00 ? 0:40     ? Logged ?
? 1/06/2015 4:00 ? NULL           ?          ? Logged ?
???????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

结果:

???????????????????????????????????????????????????????
?     Start      ?      End       ? Duration ?  Type  ?
???????????????????????????????????????????????????????
? 1/06/2015 1:00 ? 1/06/2015 1:30 ? 0:30     ? Logged ?
? 1/06/2015 1:30 ? 1/06/2015 2:00 ? 0:30     ? Break  ?
? 1/06/2015 2:00 ? 1/06/2015 3:00 ? 1:00     ? Logged ?
? 1/06/2015 3:00 ? 1/06/2015 3:20 ? 0:20     ? Break  ?
? 1/06/2015 3:20 ? 1/06/2015 4:00 ? 0:40     ? Logged ?
? 1/06/2015 4:00 ? NULL           ?          ? Logged ?
???????????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

Gio*_*uri 5

这是一个解决方案:

DECLARE @t TABLE
    (
      StartTime DATETIME ,
      EndTime DATETIME,
      EmpID int    
    )

INSERT  INTO @t
VALUES  ( '1/06/2015 1:00', '1/06/2015 1:30', 1 ),
        ( '1/06/2015 2:00', '1/06/2015 3:00', 1 ),
        ( '1/06/2015 3:20', '1/06/2015 4:00', 1 ),
        ( '1/06/2015 4:00', NULL, 1 ),
        ( '1/06/2015 1:00', '1/06/2015 1:20', 2 ),
        ( '1/06/2015 2:10', '1/06/2015 3:10', 2 ),
        ( '1/06/2015 3:20', '1/06/2015 3:30', 2 )


SELECT  StartTime, EndTime, Duration, EmpID, Logged
FROM    ( SELECT    StartTime ,
                    EndTime ,
                    DATEDIFF(mi, StartTime, EndTime) AS Duration ,                  
                    EmpID,                  
                    'Logged' AS Logged,
                    1 AS IncludeRow                  
          FROM      @t
          UNION ALL
          SELECT    EndTime ,
                    LEAD(StartTime) OVER (PARTITION BY EmpID ORDER BY StartTime ) ,
                    DATEDIFF(mi, EndTime, LEAD(StartTime) OVER (PARTITION BY EmpID ORDER BY StartTime ) ) ,                 
                    EmpID,
                    'Break' AS Logged,
                    CASE WHEN EndTime IS NULL THEN 1 ELSE 0 END AS IncludeRow                  
          FROM      @t
        ) t
WHERE   (t.StartTime IS NOT NULL OR EndTime IS NOT NULL) AND (Duration > 0 OR t.IncludeRow = 1)
ORDER BY t.EmpID, t.StartTime
Run Code Online (Sandbox Code Playgroud)

输出:

StartTime               EndTime                 Duration    EmpID   Logged
2015-01-06 01:00:00.000 2015-01-06 01:30:00.000 30          1       Logged
2015-01-06 01:30:00.000 2015-01-06 02:00:00.000 30          1       Break
2015-01-06 02:00:00.000 2015-01-06 03:00:00.000 60          1       Logged
2015-01-06 03:00:00.000 2015-01-06 03:20:00.000 20          1       Break
2015-01-06 03:20:00.000 2015-01-06 04:00:00.000 40          1       Logged
2015-01-06 04:00:00.000 NULL                    NULL        1       Logged
2015-01-06 01:00:00.000 2015-01-06 01:20:00.000 20          2       Logged
2015-01-06 01:20:00.000 2015-01-06 02:10:00.000 50          2       Break
2015-01-06 02:10:00.000 2015-01-06 03:10:00.000 60          2       Logged
2015-01-06 03:10:00.000 2015-01-06 03:20:00.000 10          2       Break
2015-01-06 03:20:00.000 2015-01-06 03:30:00.000 10          2       Logged
Run Code Online (Sandbox Code Playgroud)

您正在从表中选择第一个初始行,然后endtime从每一行中startime选择下一行(LEAD窗口函数).然后你就是union那些结果.

  • 既然又简单的解决方案 一个小的改进,如果时间连续两行,它仍然会返回一个''Break'记录.最好添加一个额外的检查`AN​​D(Type ='Logged'OR(StartTime <> EndTime AND Type ='Break'))`来删除这种情况.+ 1 (3认同)