Пример:
У меня есть гостиница, и мне нужно построить форму, где я могу видеть комнаты, которые не заняты в данное время.
Отдельные книги сохраняются в таблице базы данных SQL:
room start end
1 2017-09-01 2017-09-10
2 2017-09-12 2017-09-15
1 2017-09-01 2017-09-10
Теперь мне нужны все комнаты, где, например, клиент может получить комнату с 2017-09-10 по 2017-09-11.
Я пытался построить запрос SQL, как:
SELECT * FROM rooms WHERE room_id NOT IN (
SELECT room_id FROM bookings WHERE start <= #startTime# AND end >= #endTime#
)
Но результат не надежен. Я думаю, я не первый, кто спрашивает об этом, но я не могу найти какую-либо информацию с доктором Google.
Похоже, у вас нет данных с вашими условиями:
DECLARE @Rooms TABLE (Room_Id INT, Room VARCHAR(50) );
DECLARE @Bookings TABLE (Room_Id INT, StartDate DATE, EndDate DATE);
/**/
INSERT INTO @Rooms VALUES
(1,'Room1'),
(2,'Room2'),
(3,'Room3');
INSERT INTO @Bookings VALUES
(1, '2017-09-01', '2017-09-10'),
(2, '2017-09-12', '2017-09-15'),
(1, '2017-09-01', '2017-09-10');
SELECT *
FROM @Rooms
WHERE Room_Id NOT IN (SELECT Room_Id FROM @Bookings WHERE StartDate <= '2017-09-12' AND EndDate >= '2017-09-15' );
Результат:
+=========+=======+
| Room_Id | Room |
+=========+=======+
| 1 | Room1 |
+---------+-------+
| 3 | Room3 |
+---------+-------+
Я верю, что вы очень близки. В настоящее время вы захватываете все комнаты, где начало бронирования раньше или равно вашему времени начала, а конец бронирования больше или равен вашему времени окончания. Хотя это работает, оно не распространяется на резервирование, которое начинается в течение указанного времени бронирования, и не распространяется на резервирование, которое заканчивается в течение указанного времени бронирования.
Чтобы поймать эти записи, вам просто нужно изменить порядок ваших переменных в аргументе. Вы хотите проверить бронирование, которое начинается до вашего времени окончания, и те, которые заканчиваются после вашего времени начала. Это будет охватывать любое бронирование, которое перекрывает период, который вы ищете.
DECLARE @start DATE = '2017-09-11',
@end DATE = '2017-09-13'
SELECT * FROM rooms WHERE room_id NOT IN (
SELECT room_id FROM bookings WHERE start <= @end AND end >= @start
)
Если, например, у вас есть следующие значения:
room start end
1 2017-09-01 2017-09-10
2 2017-09-12 2017-09-15
1 2017-09-01 2017-09-10
3 2017-09-09 2017-09-12
4 2017-09-14 2017-09-17
5 2017-09-13 2017-09-17
И ваш запрос использует @start = '2017-09-11'
а также @end = '2017-09-13'
Следующие номера будут действительны (при условии 5 номеров, как показано выше): 1, 4
Попробуй это. Удалены Sub Query
SELECT R.*
FROM @Rooms R, @Bookings B
WHERE R.room_id <> B.room_id
AND B.StartDate <= '2017-09-12'AND B.EndDate >= '2017-09-15'
--Using Inner Join
SELECT R.*
FROM @Rooms R
INNER JOIN @Bookings B ON R.room_id <> B.room_id
WHERE B.StartDate <= '2017-09-12'AND B.EndDate >= '2017-09-15'