Сначала я изменил ваш запрос, чтобы использовать CTE, а не 3 уровня подзапросов. Сделано это намного легче читать.
Чтобы определить ошибочные штампы, я расширил оператор CASE в вашем запросе, который идентифицировал дублирующие штампы и пометил их для исключения. Используя функцию LEAD, я проверил следующий удар, чтобы убедиться, что он в течение 10 минут. Если это так, он помечается для исключения.
Очевидно, что это решение не идеально, но оно доставит вас туда, где вам нужно, с разумной терпимостью к ошибкам. Окно пособия может быть расширено или сокращено.
Обновление: с предоставленным вами новым набором данных он превысил 10-минутный допуск. Я поднял его до 20. Опять же, здесь есть допуск к ошибке.
Я также настроил запрос InOut, чтобы он не использовал ничего с TIMEATT = 1 в качестве времени запуска. Это гарантирует, что выходы никогда не попадут в набор данных как время начала.
В заключение я добавил еще одно условие к выходному запросу, чтобы убедиться, что время начала соответствует запрошенной дате отчета.
IF OBJECT_ID('tempdb.dbo.#temptable', 'U') IS NOT NULL
DROP TABLE #temptable;
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
);
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, 10, Time_CST) THEN 1
ELSE 0
END
AS Exclude
FROM
#temptable
)
, InOut AS
(
SELECT
Company
, [NAME]
, ID AS EmpID
, IIF(TIMEATT = 1, Time_CST, NULL) AS startTime
, LEAD(Time_CST, 1, NULL) OVER (PARTITION BY NAME ORDER BY Time_CST) AS endTime
, TIMEATT
, Time_CST
FROM
NoDoubles
WHERE
Exclude = 0
)
SELECT
Company
, [NAME]
, EmpID
, startTime
, endTime
, SUM(DATEDIFF(SECOND, startTime, endTime) / 3600.0) AS HrsWorked
FROM
InOut
WHERE
CAST(startTime AS DATE) = @reportdate
AND startTime >= @starttime
AND endTime <= @endtime
GROUP BY
Company
, [NAME]
, EmpID
, startTime
, endTime
ORDER BY
Company
, [NAME]
, startTime;
DROP TABLE #temptable