Проверка конфликтов дат в MySQL

Я пишу систему бронирования отелей. после многих исследований (включая переполнение стека) я написал этот sql, чтобы узнать свободные комнаты:

SELECT * FROM room WHERE room_id NOT IN ( SELECT room_id FROM bookings WHERE checkin <= '$check_in' AND checkout >= '$check_out' ) 

но проблема заключается в том, что он не рассматривает проверку времени 12:00:00, а проверка – 11:59:00

также не давая правильных запросов, например, в пределах диапазона дат, который он не работает, например, если я бронирую с 15-18 номера в одном номере, номер которого равен 501. Если я снова запустил запрос 17-19, то эти комнаты кажутся бесплатными, но на самом деле это должно быть занятыми.

может кто-нибудь предложить очень хороший и эффективный sql, который получит точную дату, так что никакого столкновения не будет система бронирования, потому что система будет реализована в реальности, поэтому ошибки вызовут много проблем.

заранее спасибо

Solutions Collecting From Web of "Проверка конфликтов дат в MySQL"

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

Если диапазон, определяемый параметрами $check_in и $check_out перекрывает диапазон, определенный посредством checkin и checkout в любом случае, номер забронирован. В противном случае это бесплатно.

Это значит, что:

  • Если $check_in > = checkin и $check_in <= checkout , комната ЗАБРОНИРОВАНА
  • ИЛИ Если $check_out > = checkin и $check_out <= checkout , комната ЗАБРОНИРОВАНА
  • ИЛИ Если $check_in <= checkin и $check_out > = checkout , комната ЗАБРОНИРОВАНА

Итак, вам нужно представить оба этих сценария в вашем подзапросе, чтобы получить информацию, которую вы ищете.

Кроме того, вы, надеюсь, будете использовать datetime для ваших сравнений, а не просто time , иначе у вас появятся побочные эффекты.

EDIT: SQL Query

(Имейте в виду, что есть несколько способов кожи кошки, так сказать. Я просто предоставляю пример, который поддерживает то, что у вас уже есть как можно больше. Еще раз, я также предполагаю, что checkin , checkout , $check_in и $check_out будут разрешены для типов datetime )

 SELECT * FROM room WHERE room_id NOT IN (SELECT room_id FROM bookings WHERE (checkin <= '$check_in' AND checkout >= '$check_in') OR (checkin <= '$check_out' AND checkout >= '$check_out') OR (checkin >= '$check_in' AND checkout <= '$check_out')) 

Ваша оригинальная логика была очень близка, вам просто нужно поменять значения '$check_in' и '$check_out' . То есть:

 SELECT * FROM room WHERE room_id NOT IN ( SELECT room_id FROM bookings WHERE checkin <= '$check_out' AND checkout >= '$check_in' ) 

Ответ Брайана Дрисколла фокусируется на сценариях, которые создают конфликты бронирования, так:

 ---------------|-----Booked-----|--------------- |----A1----| |----A2----| |--A3--| |----------A4----------| Case A2 & A3: checkin <= '$check_in' AND checkout >= '$check_in' Case A1 & A3: checkin <= '$check_out' AND checkout >= '$check_out' Case A4: checkin >= '$check_in' AND checkout <= '$check_out' 

Однако сенарии, которые не конфликтуют, намного проще. Их всего два:

 ---------------|-----Booked-----|--------------- |----B1----| |----B2----| Case B1: checkin > '$check_out' Case B2: checkout < '$check_in' 

Таким образом, ситуация с отсутствием конфликта между бронированием и потенциальным бронированием может быть выражена с помощью этого SQL:

 checkin > '$check_out' OR checkout < '$check_in' 

Для проверки конфликтов вместо этого нам просто нужно это отрицать. Итак, используя закон ДеМорган, отрицание:

 checkin <= '$check_out' AND checkout >= '$check_in' 

… который приходит к решению, приведенному выше.

Я думаю, это может заставить вас начать в правильном направлении …

 SELECT R.* FROM room AS R LEFT OUTER JOIN bookings AS B USING (room_id) WHERE B.room_id IS NULL OR (B.checkout < '$check_in' AND B.checkin > '$check_out') 

Здесь есть несколько хороших идей: http://forums.digitalpoint.com/showthread.php?t=63746

Кроме того, какие типы столбцов вы используете для регистрации и выписки? Вы уверены, что передаете правильно отформатированные значения в $ check_in и $ check_out?