SQL, пересекается ли событие с теми, что уже имеются в таблице
9 августа 2011
Довольно частая задача при работе с различными событиями и датами.
Имеется таблица вида:
CREATE TABLE `event` ( `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, `start_time` datetime DEFAULT NULL, `end_time` datetime DEFAULT NULL, );
Тут start_time
и end_time
не обязательно datetime
. Например, они могут быть просто int
-ами, хранящими обычный unix timestamp.
Перед вставкой очередной записи нужно убедиться, что событие не пересечётся с каким-либо уже имеющимся в базе. Решается это так:
SELECT 1 FROM event WHERE :new_start_time BETWEEN start_time AND end_time OR :new_end_time BETWEEN start_time AND end_time OR start_time BETWEEN :new_start_time AND :new_end_time OR end_time BETWEEN :new_start_time AND :new_end_time LIMIT 1
В запросе :new_start_time
и :new_end_time
соответственно начало и конец события, которое мы собираемся вставлять. Если запрос выше отдал 1
, наше новое событие с чем-то пересекается…
UPD: менее избыточные варианты (спасибо dec5e):
NOT(:new_start_time > end_time OR :new_end_time < start_time)
или через AND
:new_start_time <= end_time AND :new_end_time >= start_time
Комментарии RSS по email OK
а это не одно и то же?
Нет, это не одно и то же. Представьте (или нарисуйте), что новый интервал лежит полностью в старом (new_start_time > start_time && new_end_time < end_time). Первое условие тогда сработает, а второе - нет.
Если я ничего не упустил, то наличие всех четырех условий избыточно, любое из них можно отбросить без потери результата. А можно еще больше упростить список условий:
или через
AND
dec5e, упустил. Тест-кейс: в базе есть отрезок
4…6
, добавляем1…10
.Ну отработает же тест-кейс! :)
Получаем
TRUE
, значит пересекаются. И вариант с выбрасыванием одной любой проверки из 4 оригинальных тоже срабатывает.Все верно, согласен с dec5e
dec5e, действительно отработает. Спасибо.
Была несколько иная задача, нужно было вытащить все события входящие в промежуток между дат, решил так