Я пишу систему бронирования отелей. после многих исследований (включая переполнение стека) я написал этот 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, который получит точную дату, так что никакого столкновения не будет система бронирования, потому что система будет реализована в реальности, поэтому ошибки вызовут много проблем.
заранее спасибо
Проблема, с которой вы сталкиваетесь, заключается в том, что ваш запрос недостаточно надежный. Когда вы нарушаете проблему, у вас есть следующее:
Если диапазон, определяемый параметрами $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?