总时间不正确

时间:2018-08-08 07:21:06

标签: sql-server

我有这张表,其中包含员工的出勤情况。我想计算员工每个月花费的总时间。我能够计算每天花费的时间,但并不能增加时间并提供一个整体。

以下是指向shema的链接:https://liveweave.com/q0iBdb

这是计算每个员工每天花费时间的查询。

SELECT
CONVERT(VARCHAR(6), Datediff(second, CAST(MIN([AttendanceTimeIn]) AS TIME), CAST(MAX([AttendanceTimeOut]) AS TIME))/3600) 
       + ':' 
       + RIGHT('0' + CONVERT(VARCHAR(2), (Datediff(second, CAST(MIN([AttendanceTimeIn]) AS TIME), CAST(MAX([AttendanceTimeOut]) AS TIME)) % 3600) / 60), 2) 
       + ':' 
       + RIGHT('0' + CONVERT(VARCHAR(2), Datediff(second, CAST(MIN([AttendanceTimeIn]) AS TIME), CAST(MAX([AttendanceTimeOut]) AS TIME)) % 60) , 2 ) 

       AS HoursSpent

FROM 
[HRM].[tbl_EmployeeAttendance] [Attendance]
WHERE 
[Attendance].[RecordStatusCode] != '13' AND [Attendance].[EmpCode] = 22
AND
CAST(GETDATE()-5 AS DATE) = CAST(ISNULL([AttendanceTimeIn], [AttendanceTimeOut]) AS Date)

这是我到目前为止尝试过的

SELECT CONVERT(varchar(10), SUM(DATEDIFF(MINUTE, CAST(AttendanceTimeIn AS TIME), CAST(AttendanceTimeOut AS TIME))) / 60) + ':' + CONVERT(varchar(10), SUM(DATEDIFF(MINUTE, CAST(AttendanceTimeIn AS TIME), CAST(AttendanceTimeOut AS TIME))) % 60)
FROM [HRM].[tbl_EmployeeAttendance]
WHERE CAST(COALESCE(AttendanceTimeIn, AttendanceTimeOut) AS DATE) BETWEEN '2018-08-01' AND GETDATE()  
AND
RecordStatusCode != '13' AND EmpCode = 22

这些日期的预期输出约为55小时25分钟,但可能更多或更少。

1 个答案:

答案 0 :(得分:0)

时间差的计算可以分为总小时数和剩余的分钟和秒数。

示例片段:

-- Using a table variable for demonstration purposes
declare @EmployeeAttendance table (ID int identity(1,1) primary key, EmpCode int, AttendanceTimeIn datetime, AttendanceTimeOut datetime);
-- Simplified sample data
insert into @EmployeeAttendance (EmpCode, AttendanceTimeIn, AttendanceTimeOut) values 
 (11,'2018-08-01 09:20:00', null)
,(11,null, '2018-08-01 21:35:15')
,(12,'2018-08-01 09:00:00', null)
,(12,null, '2018-08-01 22:20:20')
,(13,'2018-08-01 09:00:00',null)
,(13,'2018-08-01 12:00:00',null)
;

-- The query
WITH EMPLOYEEATTENDANCE AS
(
   select 
   EmpCode, 
   cast(coalesce(AttendanceTimeIn, AttendanceTimeOut) as date) as AttendanceDate, 
   cast(min(AttendanceTimeIn) as time) as MinEmpTimeIn,
   cast(max(AttendanceTimeIn) as time) as MaxEmpTimeIn,
   cast(max(AttendanceTimeOut) as time) as MaxEmpTimeOut
   --,max(cast(max(AttendanceTimeOut) as time)) over (partition by cast(coalesce(AttendanceTimeIn, AttendanceTimeOut) as date)) as MaxDateTimeOut
   from @EmployeeAttendance
   where cast(coalesce(AttendanceTimeIn, AttendanceTimeOut) as date) between cast('2018-08-01' as date) and cast('2018-08-01' as date)
   group by EmpCode, cast(coalesce(AttendanceTimeIn, AttendanceTimeOut) as date)
)
SELECT 
 CONCAT(SUM(DATEDIFF(HOUR,MinEmpTimeIn, coalesce(MaxEmpTimeOut,MaxEmpTimeIn))), 
        SUBSTRING(CONVERT(varchar(30), 
                  DATEADD(ms,(SUM(DATEDIFF(SECOND,MinEmpTimeIn, coalesce(MaxEmpTimeOut,MaxEmpTimeIn)))%3600)*1000,0)
                  ,114),3,6)) as TotalTimeDiff
FROM EMPLOYEEATTENDANCE;

结果:

TotalTimeDiff
-------------
28:35:35

但是在示例数据中,只有1个EmpCode的AttendanceTimeOut。
而且与所有AttendanceTimeIn相比,它甚至太低了。
对于不完整的数据,可以预期会有不完整的结果。