我在SQL Server中建立了一个酒店预订数据库。其中三个表格如下:
这些表中的相关列是:
Booking
:BookingID
(PK),CheckInDate
,CheckoutDate
RoomBooking
:RoomBookingID
(PK),FK_Booking_ID
(FK),FK_RoomID
(FK)Room
:RoomID
(PK)现在我写了一个SQL查询(如下所示),试图找出某个日期(2017-10-02至2017-10-04)的免费房间。代码解决了问题,但变得非常复杂。我知道如何通过表CheckInDate
中的CheckOutDate
和RoomBooking
来解决这个问题,但我希望这个设置能够正常运行。您对如何使下面的代码变得简单有任何想法吗?
SELECT FK_RoomID
FROM RoomBooking
WHERE FK_RoomID IN
(SELECT FK_RoomID
FROM RoomBooking
WHERE FK_BookingID NOT IN
(SELECT BookingID
FROM Booking
WHERE CheckInDate <= '2017-10-04'
AND CheckOutDatum > '2017-10-02')
)
AND FK_RoomID NOT IN
(SELECT FK_RoomID
FROM RoomBooking
WHERE FK_BookingID IN
(SELECT FK_BookingID
FROM RoomBooking
WHERE FK_RoomID IN
(SELECT FK_RoomID
FROM RoomBooking
WHERE FK_BookingID IN
(SELECT FK_BookingID
FROM RoomBooking
WHERE FK_BookingID NOT IN
(SELECT BookingID
FROM Booking
WHERE CheckInDate <= '2017-10-04'
AND CheckOutDate > '2017-10-02')
)
)
)
AND FK_BookingID NOT IN
(SELECT FK_BookingID
FROM RoomBooking
WHERE FK_BookingID NOT IN
(SELECT BookingID
FROM Booking
WHERE CheckInDate <= '2017-10-04'
AND CheckOutDate > '2017-10-02')
)
);
答案 0 :(得分:3)
我希望这样的查询:
select r.*
from room r
where not exists (select 1
from roombooking rb join
booking b
on b.bookingid = r.bookingid
where r.roomid = rb.roomid and
'2017-10-02' < b.CheckOutDate and
'2017-10-04' >= b.CheckInDate
);
这假定在有人结账的那天可以办理入住手续。
我不明白为什么你用fk_
为某些列添加前缀。外键关系应该从具有相同名称的键(以及显式声明的键)中显而易见。许多数据库都支持ANSI标准USING
子句,并且使用不同的密钥名称会阻止您使用它。