Currently, the report uses predefined times. But sometimes employees overstay their shift and they creep into the next shift report. How do I modify the report query to look at the past sign in times to avoid this? In the TIMEATT
column 1
is entry and 2
is exit. Light blue highlights the correct entries and yellow signify incorrect entries.
Day shift report for 29th has 'Done, Jane's' entry time from night shift
Night shift report for 29th has 'Do, Jone's' entry time from day shift
Below query creates a temp table with the same data as in the screenshots.
CREATE TABLE #temptable ( [Company] nvarchar(60), [ID] int, [NAME] nvarchar(130), [TIMEATT] int, [Time_CST] datetime )
INSERT INTO #temptable
values
( N'Company Ltd.', 11111, N'Done, Jane', 1, N'2019-04-28T18:00:27' ),
( N'Company Ltd.', 11111, N'Done, Jane', 1, N'2019-04-28T18:00:28' ), --Sometimes people tap their card twice
( N'Company Ltd.', 11111, N'Done, Jane', 2, N'2019-04-29T06:00:55' ),
( N'Company Ltd.', 11111, N'Done, Jane', 1, N'2019-04-29T06:01:55' ),
( N'Company Ltd.', 11111, N'Done, Jane', 2, N'2019-04-29T06:04:55' ),
( N'Company Ltd.', 11111, N'Done, Jane', 1, N'2019-04-29T18:00:27' ),
( N'Company Ltd.', 11111, N'Done, Jane', 2, N'2019-04-30T06:13:55' ),
( N'Company Ltd.', 22222, N'Do, Jone', 1, N'2019-04-29T06:20:17' ),
( N'Company Ltd.', 22222, N'Do, Jone', 2, N'2019-04-29T06:47:12' ),
( N'Company Ltd.', 22222, N'Do, Jone', 1, N'2019-04-29T10:33:33' ),
( N'Company Ltd.', 22222, N'Do, Jone', 2, N'2019-04-29T18:05:33' ),
( N'Company Ltd.', 22222, N'Do, Jone', 1, N'2019-04-29T18:06:33' ),
( N'Company Ltd.', 22222, N'Do, Jone', 2, N'2019-04-29T18:09:33' ),
( N'Company Ltd.', 22222, N'Do, Jone', 1, N'2019-04-30T06:05:33' ),
( N'Company Ltd.', 22222, N'Do, Jone', 2, N'2019-04-30T16:05:33' )
-- Test table
-- 1 is entry and 2 is exit. Sometimes people double swipe their cards which results in two 1 entries.
select * from #temptable as T
--Report start
set deadlock_priority low;
declare @shift varchar(10) = 'night'; --Option to switch between day and night
declare @reportdate datetime = '2019-04-29'; --Date to be ran
declare @starttime datetime;
declare @endtime datetime;
select @starttime = (case
when @shift = 'day' then
convert(datetime, @reportdate) + cast('04:00:00.000' as datetime)
when @shift = 'night' then
convert(datetime, @reportdate) + cast('16:00:00.000' as datetime)
end
);
select @endtime = (case
when @shift = 'day' then
convert(datetime, @reportdate) + cast('23:59:59.000' as datetime)
when @shift = 'night' then
convert(datetime, dateadd(d, 1, @reportdate)) + cast('11:59:59.000' as datetime)
end
);
select Company
, NAME
, EmpID
, startTime
, endTime
, sum(datediff(second, startTime, endTime) / 3600.0) as HrsWorked
from
( -- sub query to get matching exit time for each entry if it exists
select Company
, NAME
, ID as EmpID
, Time_CST as startTime
, lead(Time_CST, 1, null) over (partition by NAME order by Time_CST) as endTime
, TIMEATT
, Time_CST
from
( -- subquery to exclude duplicate records
select *
from
(
select *
from
( -- subquery to identify records to ignore
select Company
, NAME
, ID
, TIMEATT
, Time_CST
, case lead(TIMEATT, 1, 0) over (partition by NAME order by Time_CST)
when TIMEATT then
1
else
0
end as Exclude
from #temptable
) a
where Exclude = 0
) t
) n
) z
where TIMEATT = 1 -- filter so left column is always entry time.
and startTime >= @starttime
and endTime <= @endtime
--and Company in (@contractornames)
group by z.Company
, z.NAME
, z.EmpID
, z.startTime
, z.endTime
order by Company
, NAME
, startTime
--DROP TABLE #temptable
So Chris's answer gave me a good format to work with. I am checking to see if anyone has an entry within 4am-12pm and an exit with 12pm-7pm will be consdered day shift and anybody else will be night shift.
set deadlock_priority low;
declare @shift varchar(10) = 'day' --Option to switch between day and night
declare @reportdate datetime = '2019-04-29' --Date to be ran
declare @starttime datetime
declare @endtime datetime
select @starttime = (case
when @shift = 'day' then
convert(datetime, @reportdate) + cast('04:00:00.000' as datetime)
when @shift = 'night' then
convert(datetime, @reportdate) + cast('16:00:00.000' as datetime)
end
)
select @endtime = (case
when @shift = 'day' then
convert(datetime, @reportdate) + cast('23:59:59.000' as datetime)
when @shift = 'night' then
convert(datetime, dateadd(d, 1, @reportdate)) + cast('11:59:59.000' as datetime)
end
)
;with NoDoubles
as (select Company
, NAME
, ID
, TIMEATT
, Time_CST
, case
when lead(TIMEATT, 1, 0) over (partition by NAME order by Time_CST) = TIMEATT then
1
/* Allow for 10 minute grace period for swipes to be excluded */
when lead(Time_CST, 1, 0) over (partition by NAME order by Time_CST) = '1900-01-01 00:00:00.000' then
0
when lead(Time_CST, 1, 0) over (partition by NAME order by Time_CST) <= dateadd(minute, 1, Time_CST) then
1
else
0
end as Exclude
from temptable)
, DayShiftEmpIds
as (select distinct
(case
when count(entertimes.ID) > 0 then
entertimes.ID
end
) as id
, 'day' as shift
--,case when count(entertimes.id)>0 then 'day' else 'night' end as [shift]
from temptable entertimes
, temptable exittimes
where entertimes.ID = exittimes.ID
and ((
(
entertimes.Time_CST >= @reportdate + cast('04:00:00' as datetime)
and entertimes.Time_CST <= @reportdate + cast('11:59:00' as datetime)
and entertimes.TIMEATT = 1
)
and
(
exittimes.Time_CST >= @reportdate + cast('12:00:00' as datetime)
and exittimes.Time_CST <= @reportdate + cast('19:59:00' as datetime)
and exittimes.TIMEATT = 2
)
)
)
group by entertimes.ID)
, NightShiftEmpIds
as (select distinct
ID
, 'night' as shift
from temptable as VCCIOT
where not exists
(
select id from DayShiftEmpIds where DayShiftEmpIds.ID = VCCIOT.ID
))
, AllEmpIdsWithShift
as (select *
from
(
select id
, shift
from DayShiftEmpIds
union
select ID
, shift
from NightShiftEmpIds
) as alldata
where alldata.shift = @shift)
, InOut
as (select Company
, NAME
, NoDoubles.ID as ID
, Time_CST as startTime
, lead(Time_CST, 1, null) over (partition by NAME order by Time_CST) as endTime
, TIMEATT
, Time_CST
from NoDoubles
inner join AllEmpIdsWithShift
on AllEmpIdsWithShift.id = NoDoubles.ID
where Exclude = 0)
select Company
, NAME
, ID
, startTime
, endTime
, sum(datediff(second, startTime, endTime) / 3600.0) as HrsWorked
from InOut
where TIMEATT = 1 -- filter so left column is always entry time.
and startTime >= @starttime
and endTime <= @endtime
group by Company
, NAME
, ID
, startTime
, endTime
order by Company
, NAME
, startTime;