Рассмотрим следующую диаграмму (извините за плохой почерк):

На приведенной выше диаграмме мы можем видеть диапазоны дат на горизонтальной оси.From_D
до To_D
представляет собой забронированный слот для определенной комнаты.Четыре случая рассматриваются для дат прилета и отъезда (обозначены A i и D i ).
Мы можем ясно видеть, что конкретная комната доступна * только когда даты прибытия и отъезда полностью либо слева, либо справа от забронированного слота.
Мы можем GROUP BY
на RoomID
и рассматривать только те комнаты, где каждыйбронирование по следующим критериям, определенным выше, с использованием предложения HAVING
.
Запрос будет выглядеть следующим образом:
SELECT RoomID
FROM bookings
GROUP BY RoomID
HAVING
SUM((From_D < :arrival AND To_D < :arrival)
OR
(From_D > :departure AND To_D > :departure)) = COUNT(*)
Демонстрация в БДСкрипка
CREATE TABLE `rooms` (
`RoomId` int(4) NOT NULL,
`RoomName` varchar(20) DEFAULT NULL,
PRIMARY KEY (`RoomId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `bookings` (
`RoomId` int(4) NOT NULL,
`From_D` date NOT NULL,
`To_d` date NOT NULL,
`B_Name` varchar(20) NOT NULL,
KEY `RoomId` (`RoomId`),
CONSTRAINT `bookings_ibfk_1` FOREIGN KEY (`RoomId`) REFERENCES `rooms` (`RoomId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `rooms` (`RoomId`, `RoomName`) VALUES
('1', 'Auditorium'),
('2', 'Room2'),
('3', 'Room3'),
('4', 'Room4'),
('5', 'Room5');
INSERT INTO `bookings` (`RoomId`, `From_D`, `To_d`, `B_Name`) VALUES
('1', '2018-11-01', '2018-11-03', 'Trance'),
('2', '2018-11-02', '2018-11-07', 'Alcoding'),
('3', '2018-11-01', '2018-11-04', 'DebSoc'),
('4', '2018-11-12', '2018-11-17', 'MunSoc'),
('5', '2018-11-03', '2018-11-06', 'Pulse');
Запрос: Проверить наличие мест в период с 2018-11-01 по 2018-11-03
SELECT RoomId
FROM bookings
GROUP BY RoomID
HAVING
SUM((From_D < '2018-11-01' AND To_D < '2018-11-01')
OR
(From_D > '2018-11-03' AND To_D > '2018-11-03')) = COUNT(*)
Результат: Только RoomId 4 доступен согласно данным выборки
| RoomId |
| ------ |
| 4 |