Это будет работать на MS SQL (TSQL) с функцией ROW_NUMBER ():
SELECT l1.UserID, l1.UserName, l1.LogTime AS BeginTime, l2.LogTime AS EndTime,
l1.LogDate, ROW_NUMBER() OVER (ORDER BY l1.LogDate, l1.LogTime) AS 'RowNumber'
FROM log l1
LEFT JOIN log l2
ON l2.UserID = l1.UserID
AND l2.LogTime > l1.LogTime
AND l2.LogDate = l1.LogDate
LEFT JOIN log l3
ON l3.UserID = l1.UserID
AND l3.LogTime < l2.LogTime AND l3.LogTime > l1.LogTime
AND l3.LogDate = l1.LogDate
WHERE l3.UserID IS NULL AND RowNumber % 2 = 1 AND l1.UserID = 1
ORDER BY l1.LogDate, l1.LogTime
Первое объединение, объединение в первый раз со всеми последующими разами для того же пользователя и даты.Второе объединение позволяет нам исключить все время в одну и ту же дату и пользователя, которые имеют время между ними, что дает нам последовательное время.Функция ROW_NUMBER позволяет нам захватывать только все остальные строки, поэтому мы получаем 9:00 - 10:00
, но не 10:00 - 11:00
.
Если нет конечного времени, вы получите NULL для EndTime.
Обратите внимание, что для периодов, которые растягиваются от одного дня до следующего, вам необходимо настроить запрос, чтобы объединить время и дату и сравнить их вместе.
Не следует пытаться возвращать результаты для более чем одного пользователя,в противном случае вы потеряете данные из-за функции мода.