需要计算加班和常规时间

时间:2017-01-17 07:01:19

标签: sql sql-server sql-server-2008 tsql

我有一张表attendance

|AttendanceresultId |   AccountID   |   Intime                  |     Outtime           |   ShiftID |       
|  1                |   1234        |   2016-06-21 06:56:00     |   NULL                |   1       |   
|  2                |   1234        |   NULL                    |   2016-06-21 17:02:00 |   1       |   
|  3                |   1234        |   2016-06-22 06:56:00     |   NULL                |   1       |   
|  4                |   1234        |   NULL                    |   2016-06-22 17:02:00 |   1       |   
|  5                |   1235        |   2016-06-21 22:55:00     |   NULL                |   3       |   
|  6                |   1235        |   NULL                    |   2016-06-22 06:00:00 |   3       |   
|  7                |   1235        |   2016-06-22 22:55:00     |   NULL                |   3       |   
|  8                |   1235        |   NULL                    |   2016-06-23 07:00:00 |   3       |       

另一张表是shift

|   ShiftId     |   Starttime   |   Endtime     |
|   1           |   07:00:00.00 |   16:00:00.00 |
|   3           |   23:00:00.00 |   06:00:00.00 |

我想计算员工的工作时间总数和时间,例如

预期产出,

|   AccountID   |   NormalHours |   OvertimeHours   |    
|   1234        |   18:08   Hrs |   02:04 Hrs       |   
|   1235        |   14:10   Hrs |   01:00 Hrs       |   

我是sql server中的新手可以任何人提出任何建议

1 个答案:

答案 0 :(得分:0)

我把它分成了四个部分来调整2008年缺乏滞后功能:

1)用于组织记录的公用表表达式(以便不依赖于身份字段)

2)在不使用滞后函数的情况下计算加班时间和加班时间

3)然后我总结那些会议记录 - 并将它们分成几小时和几分钟。

4)然后我格式化它们。

也就是说,我认为现实世界数据可能会产生问题。

更新了不使用滞后功能的版本

WITH TimeRecords (AccountID, InOutTime, Intime, OutTime, Shift,
 RowNumber) AS
(SELECT att.AccountID, COALESCE(att.Intime,att.OutTime), 
 att.Intime, att.OutTime, att.Shift,
 ROW_NUMBER() OVER(ORDER BY att.AccountID, 
                       COALESCE(att.InTime, att.OutTime) )
 FROM dbo.attendance att)
 ,  
ShiftTime AS (
        SELECT   trecout.AccountID ,
                    trecin.InTime,
                    trecout.OutTime,
                  --  sh.EndTime ,
  -- Number of Minutes for the entire shift
                    CASE WHEN trecout.OutTime IS NOT NULL
                         THEN DATEDIFF(mi,
                                       trecin.InTime,
                                       trecout.OutTime)
                         ELSE 0
                    END AS TotalTime ,
  -- Number of Minutes for overtime
                    CASE WHEN trecout.OutTime IS NOT NULL
                         THEN DATEDIFF(mi, sh.EndTime,
                                       CAST(trecout.OutTime AS TIME))
                         ELSE 0
                    END AS OverTime
           FROM     TimeRecords trecout
           JOIN     TimeRecords trecin
               ON trecout.RowNumber -1 = trecin.RowNumber

              JOIN dbo.ShiftID sh
                  ON trecout.[Shift] = sh.ShiftID
         )
         ,
  -- Summarize the data
    ShiftTimeSum
      AS ( SELECT   st.AccountID ,
                    FLOOR(SUM(st.TotalTime - st.OverTime) / 60) AS      RegularHours ,
                    SUM(st.TotalTime - st.OverTime) % 60 AS RegularMinutes ,
                    SUM(st.OverTime) / 60 AS OverTimeHours ,
                    SUM(st.OverTime) % 60 AS OverTimeMinutes
           FROM     ShiftTime st
           GROUP BY st.AccountID
         )
 -- Now format
  SELECT  sts.AccountID ,
    CAST(sts.RegularHours AS VARCHAR(5)) + ':'
    + RIGHT(CAST(( 100 + sts.RegularMinutes ) AS CHAR(3)), 2) AS RegularTime ,
    CAST(sts.OverTimeHours AS VARCHAR(5)) + ':'
    + RIGHT(CAST(( 100 + sts.OverTimeMinutes ) AS CHAR(3)), 2) AS OverTime
  FROM    ShiftTimeSum sts;