SQL: как найти двойное бронирование переговорной
Две встречи назначены на одну переговорную, но обычная проверка одинакового времени начала их не замечает. Конфликт возникает при пересечении интервалов, даже если начало и продолжительность у встреч совершенно разные. Нужна проверка занятости ресурса, а не равенства дат.
Как разобрать ситуацию
Будем считать бронирование полуоткрытым: момент начала включён, окончание свободно для следующей встречи. Для двух интервалов конфликт существует, когда начало каждого раньше конца другого. Сравниваем только одну переговорную и исключаем встречу самой с собой. Условие a.id<b.id оставляет каждую конфликтующую пару один раз.
Пример и ожидаемый результат
У комнаты R1 есть встречи 09:00–10:00, 09:30–10:30 и 10:30–11:00. Конфликтует только первая со второй. Третья начинается ровно при окончании второй, поэтому по выбранному правилу наложения нет.
WITH bookings(id,room,start_t,end_t) AS(VALUES(1,'R1','09:00','10:00'),(2,'R1','09:30','10:30'),(3,'R1','10:30','11:00'))
SELECT a.id,b.id
FROM bookings a
JOIN bookings b ON a.room=b.room AND a.id<b.id AND a.start_t<b.end_t AND b.start_t<a.end_t
ORDER BY a.id,b.id;Запрос возвращает единственную пару идентификаторов 1 и 2. Проверять только равные start_t или только попадание одного начала в интервал недостаточно для всех случаев.
Проверка перед применением
- Добавьте вложенную встречу 09:40–09:50: проверка должна заметить конфликт, даже если обе её границы находятся внутри другой.
- Добавьте такую же встречу в другую комнату: межкомнатного конфликта быть не должно.
- Проверьте отменённую бронь и заранее решите, участвует ли она в занятости.
Для оператора полезно показать обе встречи и величину наложения, а не просто красный счётчик конфликтов. Если между встречами требуется десять минут на подготовку, этот буфер становится частью интервала занятости. Его нужно добавить в модель явно и повторить контроль на соседних по времени событиях.
Границы решения
Пример использует одинаковую дату и нормализованное время. Для перехода через полночь храните полные временные отметки. Поиск конфликтов в отчёте не предотвращает одновременную запись двух броней: при создании нужен отдельный механизм согласованности.
Если запросы уже пишутся, а уверенности в кардинальности, оконных рамках и проверке результата не хватает, продолжить практику можно в нашем платном курсе
Продвинутый SQL: сложные запросы и задачи для собеседований. Перед записью сравните программу со своей задачей и подготовкой.
Техническая справка: www.sqlite.org: документация, www.sqlite.org: документация.
Следующий шаг: Сложные SQL-запросы: разборы расчётов и ошибок. По смежным вопросам: Частичные возвраты в SQL: как найти заказ, которому вернули больше оплаты, Как разбить события на сессии в SQL по паузе между действиями.
