Извините, если заголовок немного туманный.
У меня есть база данных, выглядящая так:
orderid | roomname | date(DATE) | from(TIME) | to(TIME)
Пример-данные:
1231 | E12 | 2013-04-05 | 07:00:00 | 10:00:00 1671 | E12 | 2013-04-05 | 13:00:00 | 14:00:00
Например, я ищу подходящую дату и, очевидно, получаю все оговорки в этот день. Как вы можете видеть на примерах данных, номер доступен с 10:00 до 13:00. Как я могу это поймать?
Я думал о том, чтобы перебирать время 07: 00: 00-16: 00: 00 (по одному запросу для каждого) и проверить, получаю ли я какие-либо результаты из sql. Если я получу результаты, я буду знать, что номер занят, но поскольку здесь неизвестно (например, 08:00:00 и 09:00:00 не существует), я получу ложные срабатывания.
Какие-нибудь советы здесь?
Одним из способов было бы использовать «таблицу календаря», или если вы только когда-нибудь заинтересованы в один день, то «таблица часов» будет делать. Ниже показано (примерно), как вы его используете.
SELECT clock.time AS available FROM clock LEFT JOIN bookings ON clock.time BETWEEN bookings.from AND bookings.to AND bookings.date = '2013-01-01' WHERE bookings.id IS NULL
http://www.brianshowalter.com/calendar_tables – пример создания календаря в MySQL
С этими данными:
create table rooms ( orderid int not null, roomname varchar(8) not null, date date not null, `from` time not null, `to` time not null ); insert into rooms values (1231, 'E12', '2013-04-05', '07:00', '10:00'); insert into rooms values (1671, 'E12', '2013-04-05', '13:00', '14:00');
для получения доступного временного интервала / слота вы можете задать этот запрос:
SELECT DATE_FORMAT(r1.`to`, '%T') AS `From`, DATE_FORMAT(min(r2.`from`), '%T') AS `To` FROM rooms r1 JOIN rooms r2 ON r1.`to`< r2.`from` WHERE r1.date = '2013-04-05' AND r1.roomname = 'E12' GROUP BY r1.`to` HAVING NOT EXISTS (SELECT NULL FROM rooms r3 WHERE r1.`to` < r3.`to` AND min(r2.`from`) > r3.`from`)
приведенный выше запрос вернется:
10:00:00 13:00:00
Вот скрипт SQL: http://sqlfiddle.com/#!2/3c124/25
Примечание: вышеупомянутый запрос был любезно адаптирован из этого ответа @fthiella :
https://stackoverflow.com/a/14139835/114029
С помощью этого дополнительного запроса:
SELECT (COUNT(*) = 0) AS Available FROM rooms WHERE roomname = 'E12' AND date = '2013-04-05' AND ( (`from` < MAKETIME(10,00,00) AND `to` > MAKETIME(10,00,00)) OR (`from` < MAKETIME(13,00,00) AND `to` > MAKETIME(13,00,00)) )
Он вернется 1
, то есть нет резервации между заданным временем начала ( from
) и временем окончания ( to
), и поэтому комната доступна.
Вот скрипт SQL для воспроизведения с данными: http://sqlfiddle.com/#!2/3c124/1