Вы хотите исключить конфликтующие бронирования.
Давайте начнем с рассмотрения запрашиваемого периода (A ... B) и гипотетического резервирования (C ... D), мы можем отобразить все возможности и увидеть, что есть несколько возможностей для конфликта:
A.....B C.....D OKAY: note B < C never happens otherwise
A........C..B..D NOT OKAY (B inside C..D)
A........C.....D..B NOT OKAY (C inside A..B, D inside A..B)
C..A..D..B NOT OKAY (A inside C..D, D inside A..B)
C.A.B.D NOT OKAY (A inside C..D, B inside C..D)
C.....D A..B OKAY: note A > D never happens otherwise
A...B OKAY (no C...D reservation at all)
Таким образом, в принципе, ни один из элементов этого интервала не должен находиться внутри другого интервала:
NOT (
(:dateIn BETWEEN rs.date_in AND rs.date_out)
OR
(:dateOut BETWEEN rs.date_in AND rs.date_out)
OR
(rs.date_in BETWEEN :dateIn AND :dateOut)
OR
(rs.date_out BETWEEN :dateIn AND :dateOut)
)
и это должно включать в себя сбой запроса (нет записи rs вообще).
Видя ту же диаграмму, мы также видим, что можем просто запросить B
rs.date_in > :dateOut OR rs.date_out < :dateIn
И так как вам нужны комнаты, для которых нет конфликта, вы должны поместить приведенный выше запрос в предложение JOIN, предназначенное для find конфликтов, с LEFT JOIN и запросом «no конфликта» (rs info равен NULL) в WHERE, чтобы определить, где не выполняется предложение JOIN:
SELECT rooms.*
FROM rooms
LEFT JOIN reservations ON
(
rooms.id = reservations.room_id
AND (
NOT (reservations.date_in > :dateOut OR reservations.date_out < :dateIn)
)
)
) WHERE rooms.id = :id AND reservations.room_id IS NULL
Предложение JOIN можно упростить, поскольку NOT (A OR B)
равно NOT A AND NOT B
, а NOT >
равно <=
:
(
rooms.id = reservations.room_id
AND reservations.date_in <= :dateOut
AND reservations.date_out >= :dateIn
)
, который немедленно сообщает нам удобный индекс для reservations
:
CREATE INDEX reservations_chk ON reservations(room_id, date_in, date_out, rs_id);
Вы хотите проверить это и проверить, что происходит, когда резервирование заканчивается в один день, и запрос начинается в тот же день (и то же самое с резервированием, начинающимся по окончании запроса). В зависимости от политики отеля вы можете исключить равенство из одного или обоих условий ограничения. Это связано с тем, что дни базы данных «начинаются» и «заканчиваются» в полночь, но реальные резервирования могут начинаться, скажем, в 11:00 и заканчиваться в 10:00, чтобы обеспечить уборку и подготовку комнаты.
Видя, что такой запрос может содержать ключевые слова SELECT, JOIN, бронирование, номер, доступные и т. Д., Вы можете найти в Google и найти также такие документы, как this или this , или это в переполнении стека, что может быть интересно (я только кратко их рассмотрел - caveat emptor ).