Something like this should work:
WITH cteDates As
(
SELECT
EmployeeID,
EmployeeName,
Designation,
CASE InputType
WHEN 'Time In' THEN 0
ELSE 1
END As IsTimeOut,
WorkingDate,
TimeInput,
DateAdd(day, DateDiff(day, '19000101', WorkingDate), Cast(TimeInput As datetime2(0))) As LogTime,
ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY WorkingDate, TimeInput) As RN
FROM
@AD
)
SELECT
I.EmployeeID,
I.EmployeeName,
I.Designation,
I.WorkingDate,
I.TimeInput As CheckIn,
O.TimeInput As CheckOut,
Cast(DateDiff(minute, I.LogTime, O.LogTime) / 60. As decimal(18, 2)) As [Hours]
FROM
cteDates As I
LEFT JOIN cteDates As O
ON O.EmployeeID = I.EmployeeID
And O.RN = I.RN + 1
WHERE
I.IsTimeOut = 0
;
Output:
EmployeeID EmployeeName Designation WorkingDate CheckIn CheckOut Hours
EMP101 Samuel Osei Banahene Deputy MD 2017-01-12 08:08:00 17:35:00 9.45
EMP102 Andrews Appiah Sarkodie Managing Director 2017-01-12 08:12:00 17:35:00 9.38
EMP103 Nancy Koffour Department Head 2017-01-12 08:10:00 17:37:00 9.45
EMP104 George Mensah Supervisor 2017-01-12 08:10:00 17:38:00 9.47
EMP105 Success Abena Gyasiwaa Marketing Manager 2017-01-12 08:07:00 17:40:00 9.55
Notes:
If you have an overnight shift, it should calculate the hours correctly, but the
WorkingDate
column will be the date that the shift started.
If an employee checks out without checking in first, the check out will be dropped.
If an employee checks out twice without checking in between the two events, the later check out will be dropped.
If an employee has checked in and hasn't checked out again yet, you will get
Null
in the
CheckOut
and
Hours
columns.
If an employee checks in twice without checking out between the two events, they are assumed to have checked out and back in at the same time.
Eg: (Time In at 08:07, Time In at 08:37, Time Out at 17:40) will produce (In 08:07, Out 08:37, 0.5 Hours) and (In 08:37, Out 17:40, 9.05 Hours)
If you would rather return
Null
in the
CheckOut
and
Hours
columns, you can add
And O.IsTimeOut = 1
to the
LEFT JOIN
conditions:
FROM
cteDates As I
LEFT JOIN cteDates As O
ON O.EmployeeID = I.EmployeeID
And O.RN = I.RN + 1
And O.IsTimeOut = 1