Использование инструкции «Not In» в sql для дублированного ключа

#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, Изображение 2

Ответ №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. Спасибо за ответ. Если существует какое-либо существующее бронирование для отеля, то код не возвращает результата. При отсутствии бронирования возвращаются все доступные идентификаторы номеров.