【问题标题】:Using "Not In" statement in sql for a duplicated key在 sql 中使用“Not In”语句获取重复键
【发布时间】:2011-05-09 16:45:54
【问题描述】:

我的问题是:

有一个 sql 存储过程,它为我提供给定 hotelidbookinbookout 日期的 hotel_reservation 表中两个日期之间的空闲房间列表。

程序如下:

    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_idHotel_id 的重复键,因为 ID 为 201 的酒店可以有 room_id 101,ID 为 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

问题是:

当我运行此程序时,如果用户在酒店 201 预订了 id 为 101 的房间,另一个用户在 id 为 202 的酒店中看不到 id 为 101 的房间。它从酒店预订了所有 101 id 的房间。

如何改进我的程序来克服这个问题?

感谢观看..

Image1, Image2

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    更改为允许多个条件的 NOT EXSTS?

    在这种情况下,它可以检查两个酒店房间ID。

    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 运算符优先级

    【讨论】:

    • 删除最后一个“R.hotel_id = @hotel_id”条件然后可能。没有样本数据很难判断
    • 所有 ORed 条件都应该用括号括起来。顺便说一句,只要两个就足够了:@DateStart BETWEEN H.bookingStart AND H.bookingEnd or H.bookingStart BETWEEN @DateStart AND @DateEnd(我的意思是,只有 四个日期检查中的两个。当然,还需要加入条件。)
    • 感谢您的帮助,当我将 OR 括起来时效果很好。
    • @Andriy M:老天,我怎么会错过呢?谢谢你。 [/facepalm]
    • @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
    

    【讨论】:

    • 感谢您的回复。如果是否有任何现有的酒店预订,则代码不返回任何结果。当没有预订时,它会返回所有可用的房间 ID。
    猜你喜欢
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    相关资源
    最近更新 更多