#sql #sql-server
#sql #sql-сервер
Вопрос:
Мой вопрос:
Есть хранимая процедура sql, которая выдает мне список свободных номеров между двумя датами в таблице hotel_reservation для заданных дат hotelid
и bookin
, bookout
.
Вот процедура :
ALTER PROCEDURE dbo.StoredProcedure1
(
@DateStart date,
@DateEnd date,
@hotel_id int
)
AS
SELECT DISTINCT room_type_id, room_id
FROM Room
WHERE room_id NOT IN (
SELECT room_id
FROM Hotel_Reservation
WHERE @DateStart BETWEEN bookingStart AND bookingEnd
OR @DateEnd BETWEEN bookingStart AND bookingEnd
or bookingStart BETWEEN @DateStart AND @DateEnd
or bookingEnd BETWEEN @DateStart AND @DateEnd
and hotel_id = @hotel_id
) and hotel_id = @hotel_id
RETURN
Определение Room
таблицы :
room_id int
hotel_id int
room_type_id varchar
price money
room_description varchar
В таблице room я использовал дублированный ключ с room_id
и Hotel_id
потому что отель с идентификатором 201 может иметь room_id
101, также отель с идентификатором 202 может иметь room_id
101, чтобы избежать повторяющихся столбцов, которые я использовал это.
определение hotel_reservation table
reservation_id int
customer_id varchar
bookingStart date
bookingEnd date
status varchar
room_id int
hotel_id int
date date
Проблема в:
Когда я запускаю эту процедуру, если пользователь забронировал номер с идентификатором 101 в отеле 201, другой пользователь не может увидеть номер с идентификатором 101 в отеле с идентификатором 202. Он бронирует все 101 идентификационный номер из отелей.
Как я могу улучшить свою процедуру, чтобы преодолеть эту проблему?
Спасибо за просмотр..
Ответ №1:
Изменить на NOT EXSTS, который допускает несколько условий?
В этом случае он может проверять идентификаторы как отеля , так и номера.
SELECT DISTINCT room_type_id, room_id
FROM Room R
WHERE NOT EXISTS (
SELECT *
FROM Hotel_Reservation H
WHERE
(
@DateStart BETWEEN H.bookingStart AND H.bookingEnd
OR @DateEnd BETWEEN H.bookingStart AND H.bookingEnd
or H.bookingStart BETWEEN @DateStart AND @DateEnd
or H.bookingEnd BETWEEN @DateStart AND @DateEnd
)
and --here is where we check **that room for that hotel**
H.hotel_id = R.hotel_id and H.room_id = R.room_id
)
and
R.hotel_id = @hotel_id
Редактировать:
Спасибо Andriy M за исправление моего приоритета оператора AND / OR с некоторыми скобками
Комментарии:
1. Измените последнее условие «R.hotel_id = @hotel_id», тогда, возможно. Трудно сказать без примеров данных
2. Все указанные условия должны быть заключены в квадратные скобки. И, кстати, достаточно только двух из них:
@DateStart BETWEEN H.bookingStart AND H.bookingEnd or H.bookingStart BETWEEN @DateStart AND @DateEnd
(Я имею в виду, только двух из четырех проверок даты . Условие объединения, конечно, тоже необходимо.)3. Спасибо за вашу помощь, которая хорошо сработала, когда я заключил редакторы в квадратные скобки.
4. @Andriy M: Господи, как я это пропустил? Спасибо. [/facepalm]
5. @Recep Я рад, что это сработало. Не забудьте отметить ответ!
Ответ №2:
Вот краткий обзор возможного решения. (извините, у меня не было времени протестировать это …)
ALTER PROCEDURE dbo.StoredProcedure1 (
@DateStart date,
@DateEnd date,
@hotel_id int
)
AS
;WITH BookedRooms ( roomID )
AS (
SELECT room_id
FROM Hotel_Reservation
WHERE hotel_id = @hotel_id
AND ( @DateStart BETWEEN bookingStart AND bookingEnd
or @DateEnd BETWEEN bookingStart AND bookingEnd )
)
SELECT DISTINCT room_type_id, room_id
FROM Room
WHERE room_id NOT IN (
SELECT room_id
FROM BookedRooms
)
and hotel_id = @hotel_id
RETURN
Комментарии:
1. Спасибо за ответ. Если существует какое-либо существующее бронирование для отеля, то код не возвращает результата. При отсутствии бронирования возвращаются все доступные идентификаторы номеров.