Получить следующий доступный временной интервал после определенного времени в MySQL - PullRequest
0 голосов
/ 06 января 2019

Я пытаюсь получить следующий доступный интервал времени, проверяя список зарезервированных времен в таблице. Каждое резервирование может быть минимумом увеличения на 1 час и может продолжаться весь день. Так, например, если номер забронирован с 9:00 до 10:00 и с 12:00 до 15:00, и я пытаюсь получить первый доступный слот после 9:00. Будет 10 утра.

Я могу оставить соединение на столе и получить доступность комнаты, но только не временные интервалы.

Вот моя связанная схема:

Бронирование

res_id | hotel_id | room_id | res_start | res_end

Номера:

room_id | hotel_id | room_name | room_number

Вот мой запрос:

SELECT free_from, free_until
FROM (
  SELECT a.res_end AS free_from,
  (SELECT MIN(c.res_start)
   FROM reservations c
   WHERE c.res_start > a.res_end) as free_until
   and b.res_end > "2019-01-05 11:00:00"
  FROM reservations a
  WHERE NOT EXISTS (
    SELECT 1
    FROM reservations b
    WHERE b.res_start > a.res_end
  )
) as d
ORDER BY free_until-free_from

Но мне возвращают неверное время.

Ожидаемый результат:

room_id | room_name | Next available time
1       | "Single"  | 2019-01-05 10:00:00

Вот таблица временных интервалов

CREATE TABLE time_slots
    (`slot` time);

INSERT INTO time_slots
    (`slot`)
VALUES
    ('00:00:00'),
    ('01:00:00'),
    ('02:00:00'),
    ('03:00:00'),
    ('04:00:00'),
    ('05:00:00'),
    ('06:00:00'),
    ('07:00:00'),
    ('08:00:00'),
    ('09:00:00'),
    ('10:00:00'),
    ('11:00:00'),
    ('12:00:00'),
    ('13:00:00'),
    ('14:00:00'),
    ('15:00:00'),
    ('16:00:00'),
    ('17:00:00'),
    ('18:00:00'),
    ('19:00:00'),
    ('20:00:00'),
    ('21:00:00'),
    ('22:00:00'),
    ('23:00:00');

Ответы [ 2 ]

0 голосов
/ 06 января 2019

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

SELECT rm.room_id, rm.room_name, MIN(re.res_end) AS `available from`
FROM reservations re
LEFT JOIN reservations rs ON rs.hotel_id = re.hotel_id AND rs.room_id = re.room_id AND rs.res_start = re.res_end
JOIN rooms rm ON rm.hotel_id = re.hotel_id
WHERE rs.res_id IS NULL AND re.res_end > NOW()
GROUP BY rm.room_id, rm.room_name

Вывод (для моей маленькой демонстрации на dbfiddle ):

room_id     room_name   available from
1           Single      2019-01-06 10:00

Обновление

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

SELECT rm.room_id, rm.room_name,
       MIN(t.slot) AS `available from`
FROM time_slots t
CROSS JOIN rooms rm
LEFT JOIN reservations r ON HOUR(t.slot) BETWEEN HOUR(r.res_start) AND HOUR(r.res_end) - 1 
                        AND DATE(r.res_start) = DATE(@time)
                        AND r.hotel_id = rm.hotel_id
                        AND r.room_id  = rm.room_id
WHERE t.slot > @time AND r.res_id IS NULL
GROUP BY rm.room_id, rm.room_name
ORDER BY rm.room_id

В этом запросе вы заменили бы @time на интересующее вас время. Я обновил демо на dbfiddle , чтобы продемонстрировать запрос, вы можете поиграть с настройкой переменной @time, чтобы посмотреть, как она работает.

0 голосов
/ 06 января 2019

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

SELECT 
    roo.hotel_id,
    roo.room_id,
    roo.room_name,
    MIN(res.res_end) next_available_time
FROM 
    reservations res
    INNER JOINS rooms roo 
        ON  roo.hotel_id = res.hotel_id 
        AND roo.room_id  = res.room_id
WHERE 
    res.res_end > "2019-01-05 11:00:00"
    AND NOT EXISTS (
        SELECT 1 
        FROM reservations
        WHERE 
            res_start = res.res_end 
            AND hotel_id = res.hotel_id 
            AND room_id  = res.room_id
    ) 
GROUP BY 
    res.hotel_id,
    res.room_id,
    roo.room_name

Проверено в этой скрипке БД .

Я предполагал, что оба столбца hotel_id и room_id используются для объединения таблиц (если достаточно room_id, это немного сократит запрос).

...