SQL Захват наличия номеров в отеле между двумя датами

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

Вот что у меня есть:

SELECT r.FLOOR, r.ROOM
FROM BOOKING b, ROOMS r
WHERE TO_DATE('2015-03-28', 'YYYY-MM-DD')
BETWEEN TO_DATE(b.CHECKIN, 'YY-MM-DD') AND TO_DATE(b.CHECKOUT, 'YY-MM-DD')
AND r.ROOMID = b.ROOMID;

Это просто возвращает обратно все занятые номера на указанную дату. (2015-03-28)

Как я могу изменить этот код, чтобы он принимал две даты, регистрировался и выписывался, а также предоставлял свободные номера вместо занятых.

Любая помощь высоко ценится!


person Jon Perron    schedule 31.03.2015    source источник


Ответы (3)


Вы можете использовать функцию Oracle wm_overlaps, которая находит перекрывающиеся промежутки времени:

select *
from rooms
where roomid not in 
(
  select b.room_id
  from booking b
  where wm_overlaps (
    wm_period(b.checkin, b.checkout),
    wm_period(
      to_date('2014-01-01', 'yyyy-mm-dd'), 
      to_date('2014-01-05', 'yyyy-mm-dd')
    )
  ) = 1
)

В этом запросе у номеров нет бронирований между обоими заданными параметрами.

person guthy    schedule 31.03.2015
comment
Это именно то, что я искал! Я немного изменил его, чтобы лучше соответствовать нужным мне результатам. select bu.name, r.floor, r.room from rooms r, building bu, roomtypes rt where r.ROOMTYPEID = rt.ROOMTYPEID AND rt.BUILDINGID = bu.BUILDINGID AND roomid not in ( select b.roomid from booking b where wm_overlaps ( wm_period(b.checkin, b.checkout), wm_period( to_date('2015-03-25', 'yyyy-mm-dd'), to_date('2015-04-05', 'yyyy-mm-dd') ) ) = 1 ) ORDER BY r.floor; - person Jon Perron; 31.03.2015

Попробуйте получить список всех номеров и исключить из него забронированный набор, например

SELECT r.FLOOR, r.ROOM
FROM ROOMS r
EXCEPT
SELECT r.FLOOR, r.ROOM
FROM BOOKING b, ROOMS r
WHERE TO_DATE('2015-03-28', 'YYYY-MM-DD')
BETWEEN TO_DATE(b.CHECKIN, 'YY-MM-DD') AND TO_DATE(b.CHECKOUT, 'YY-MM-DD')
AND r.ROOMID = b.ROOMID;
person olga    schedule 31.03.2015
comment
Интересно... Я использую несколько примеров в Интернете, но все они дают мне синтаксические ошибки, я использую Oracle, может быть, проблема в этом? - person Jon Perron; 31.03.2015
comment
Какую ошибку вы получили? В Oracle вместо этого вы можете попробовать использовать MINUS, ЗА ИСКЛЮЧЕНИЕМ - person olga; 31.03.2015
comment
Да, переключение на МИНУС сработало, теперь как мне получить тот же результат, но с двумя датами? Скажем, я хочу сделать несколько дат, например: с 28 марта 2015 г. по 05 апреля 2015 г. - person Jon Perron; 31.03.2015

Это может быть ближе. Замените параметры (отмеченные @) на соответствующие:

SELECT r.FLOOR, r.ROOM
FROM ROOMS r
WHERE r.ROOMID NOT IN (
    -- exclude rooms where checkin or checkout overlaps with the desired dates
    SELECT r.ROOMID
    FROM BOOKING b
    WHERE (
            b.CHECKIN  BETWEEN TO_DATE(@CHECKIN, 'YY-MM-DD') AND TO_DATE(@CHECKOUT, 'YY-MM-DD')
        OR  b.CHECKOUT BETWEEN TO_DATE(@CHECKIN, 'YY-MM-DD') AND TO_DATE(@CHECKOUT, 'YY-MM-DD')
    )
person shawnt00    schedule 31.03.2015