Это проблема с пробелами и островами.
Для начала вы можете сгенерировать группы последовательных записей с помощью следующего запроса:
SELECT [Mode], MIN(id) min_id, MAX(id) max_id, MIN([Date]) min_date, MAX([Date]) max_date
FROM (
SELECT
id,
[Date],
[Mode],
ROW_NUMBER() OVER(ORDER BY [Date]) rn1,
ROW_NUMBER() OVER(PARTITION BY [Mode] ORDER BY [Date]) rn2
FROM mytable
) x
GROUP BY [Mode], (rn1 - rn2)
Это дает:
Mode | min_id | max_id | min_date | max_date
:--- | -----: | -----: | :--------------- | :---------------
IN | 1 | 6 | 2019-09-20 09:28 | 2019-09-20 19:01
Out | 7 | 7 | 2019-09-20 19:01 | 2019-09-20 19:01
IN | 8 | 9 | 2019-09-20 20:28 | 2019-09-20 20:35
Out | 10 | 11 | 2019-09-20 20:50 | 2019-09-20 20:55
IN | 12 | 12 | 2019-09-20 21:30 | 2019-09-20 21:30
Затем вы можете превратить этот запрос в cte и самостоятельно присоединиться к нему для генерации ожидаемого набора результатов:
WITH cte AS (
SELECT [Mode], MIN(id) min_id, MAX(id) max_id, MIN([Date]) min_date, MAX([Date]) max_date
FROM (
SELECT
id,
[Date],
[Mode],
ROW_NUMBER() OVER(ORDER BY [Date]) rn1,
ROW_NUMBER() OVER(PARTITION BY [Mode] ORDER BY [Date]) rn2
FROM mytable
) x
GROUP BY [Mode], (rn1 - rn2)
)
SELECT c1.min_id IdIn, c1.min_date DateIN, c2.max_id IdOut, c2.max_date DateOut
FROM cte c1
INNER JOIN cte c2
ON c1.mode = 'IN'
AND c2.mode = 'Out'
AND c2.min_id = c1.max_id + 1
Вывод:
IdIn | DateIN | IdOut | DateOut
---: | :--------------- | ----: | :---------------
1 | 2019-09-20 09:28 | 7 | 2019-09-20 19:01
8 | 2019-09-20 20:28 | 11 | 2019-09-20 20:55
Демонстрация на DB Fiddle