Этот запрос должен дать вам нужный вам результат. Он работает, выбирая каждую запись и соединяя ее со следующим выходом того же сотрудника (записи без дальнейших выходов игнорируются): это дает нам продолжительность смены сотрудника. Затем результаты агрегируются, и длительности смены суммируются в каждой группе.
SELECT
t1.empid,
t1.department,
YEAR(t1.timestamp) Year,
MONTH(t1.timestamp) Month,
CONVERT(
varchar(12),
DATEADD(minute, SUM(DATEDIFF(minute, t1.timestamp, t2.timestamp)), 0),
114
) TotalHours
FROM
mytable t1
INNER JOIN mytable t2
ON t1.empid = t2.empid
AND t2.read_id = 2
AND t2.timestamp = (
SELECT MIN(timestamp)
FROM mytable
WHERE
read_id = 2
AND empid = t2.empid
AND timestamp > t1.timestamp
)
WHERE
t1.read_id = 1
GROUP BY t1.empid, t1.department, YEAR(t1.timestamp), MONTH(t1.timestamp)
ORDER BY 1, 2, 3, 4
Возвращает:
empid | department | Year | Month | TotalHours
----: | :--------- | ---: | ----: | :-----------
3221 | IT | 2017 | 1 | 15:24:00:000
5565 | IT | 2017 | 1 | 02:00:00:000
Демонстрация DB Fiddle на SQL Server 2014
Однако существует крайний случай, когда сотрудник входит дважды, а затем существует (это происходит в ваших данных, когда сотрудник 5565
входит в 29/01/2017 12:28:06
и в 29/01/2017 12:28:07
, а затем выходы на 29/01/2017 13:28:06
. Приведенный выше запрос учитывает две перекрывающиеся записи и сопоставляет их с одним и тем же выходом, в результате чего этот час работы учитывается дважды.
Хотя это соответствует вашим ожидаемым результатам, это то, что вы действительно хотите? Вот альтернативный запрос, который, если происходит несколько последовательных записей одного и того же сотрудника, учитывает только последний:
SELECT
t1.empid,
t1.department,
YEAR(t1.timestamp) Year,
MONTH(t1.timestamp) Month,
CONVERT(
varchar(12),
DATEADD(minute, SUM(DATEDIFF(minute, t1.timestamp, t2.timestamp)), 0),
114
) TotalHours
FROM
mytable t1
INNER JOIN mytable t2
ON t1.empid = t2.empid
AND t2.read_id = 2
AND t2.timestamp = (
SELECT MIN(timestamp)
FROM mytable
WHERE
read_id = 2
AND empid = t2.empid
AND timestamp > t1.timestamp
)
WHERE
t1.read_id = 1
AND NOT EXISTS (
SELECT 1
FROM mytable
WHERE
read_id = 1
AND empid = t1.empid
AND timestamp > t1.timestamp
AND timestamp < t2.timestamp
)
GROUP BY t1.empid, t1.department, YEAR(t1.timestamp), MONTH(t1.timestamp)
ORDER BY 1, 2, 3, 4
Возвращает:
empid | department | Year | Month | TotalHours
----: | :--------- | ---: | ----: | :-----------
3221 | IT | 2017 | 1 | 15:24:00:000
5565 | IT | 2017 | 1 | 01:00:00:000
Скрипка БД