@skyfly2010

Как сделать сравнение диапазонов дат в mysql?

Доброго дня, джентльмены. Есть следующая задача:
Есть база данных в которую записаны даты начала и завершения мероприятий, например:
  • id:1, start:2019-02-10, final: 2019-02-15.
  • id:2, start:2019-02-20, final: 2019-02-22.
  • id:3, start:2019-02-25, final: 2019-02-28.

И так далее.
Необходимо составить запрос таким образом, чтобы он проверял можно ли между уже имеющимися мероприятиями добавить еще одно. Т.е. если мы приходит start:2019-02-16, final:2019-02-18, то запрос должен вернуться пустым. Это будет означать, что можно добавить еще одно мероприятие. Если же начало или конец мероприятия налагается на другое мероприятие, то запрос должен вернуться с id того мероприятия(ий), которое попало в диапазон нового мероприятия.
5c4ed2cd5c661052764732.jpeg
Рисунок 1.
Черный штрих - это время.
Зеленые эллипсы - это запланированные мероприятия.
Красные эллипсы - это мероприятия, которые запланировать не возможно.
Синий эллипс - это мероприятие, которое можно запланировать.
Нашел в интернете такой пример: airbnb.ru, да собственно в любом сервисе по бронированию чего-либо это есть.
Подскажите, как можно это сделать или дайте почитать, где это может быть описано. Если у кого-то есть живой пример реализации на php или js, то буду очень благодарен за ссылку.
  • Вопрос задан
  • 494 просмотра
Решения вопроса 1
@luna3956
select id
from Table1
where
    "2019-02-16" between start and final or
    "2019-02-18 " between start and final


Если запрос ничего не вернул, значит пересечений нет и мероприятие можно назначить, в противном случае запрос вернет Id мероприятий, в диапазон которых попадает новое мероприятие

UPD:
Код выше глядя на рисунок предложил, однако может быть случай, когда новое мероприятие начинается ранее существующих и заканчивается позже них, чтобы охватить и такой сценарий лучше сделать так:

select id
from Table1
where
    start <= "2019-02-18 and final >= "2019-02-16"
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Можно и короче записать
SELECT COUNT(*) AS `count`
  FROM `table`
  WHERE :start <= `final` AND :final >= `start`
Ответ написан
Комментировать
@Vitsliputsli
оптимальнее, с точки зрения производительности, будет так:
SELECT 1
FROM `table`
WHERE :start <= `final` AND :final >= `start`
LIMIT 1
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы