Group By子句是否需要连接?

时间:2015-02-06 20:19:16

标签: sql

鉴于此架构:

Hotel(hotelNo, hotelName, city)                      #hotelNo is PK
Room (roomNo, hotelNo, type, price)                  #(roomNo, hotelNo) is PK
Booking (hotelNo, guestNo, dateFrom, dateTo, roomNo) #(hotelNo,guestNo, dateFrom) is PK
Guest(guestNo, GuestName, GuestAddress)              #guestNo is PK

问: 今天每间酒店空置房间的收入损失是多少?

在解决方案时,我得到了一个非常不同的答案(更复杂,但基本上我找到all rooms in hotels并计算Difference设置运算符对all rooms which are booked today然后计算出的价格剩下的房间有一个分组条款 - 我甚至不确定它会起作用,但在纸面上看起来有效。但是,看一下示例解决方案:

SELECT hotelNo, SUM(price) FROM Room r
WHERE roomNo NOT IN
    (SELECT roomNo FROM Booking b, Hotel h
    WHERE (dateFrom <= CURRENT_DATE AND
        dateTo >= CURRENT_DATE) AND
        b.hotelNo = h.hotelNo)
GROUP BY hotelNo; 

为什么我们需要加入预订和酒店。我看到我们加入了基于b.hotelNo=h.hotelNo的两个关系,但是看一下架构,预订提供了关于RoomNo(已预订)的详细信息,并提供了有关哪个酒店和日期的信息......当然这就是我们的所有信息需要使用Group By子句来实现我们想要的结果吗?还是我弄错了?

2 个答案:

答案 0 :(得分:1)

您不需要hotel表。 booking中的外键值适用于比较,假设所有预订确实适用于酒店。

这应该可以正常工作,即使需要HotelNoRoomNo来识别预订和房间:

SELECT hotelNo, SUM(price)
FROM Room r
WHERE r.roomNo NOT IN (SELECT b.roomNo
                       FROM Booking b
                       WHERE (dateFrom <= CURRENT_DATE AND dateTo >= CURRENT_DATE) AND
                             b.hotelNo = r.hotelNo
                      )
GROUP BY hotelNo; 

然而,拆分像这样的配对关系是很尴尬的。请改用not exists

SELECT hotelNo, SUM(price)
FROM Room r
WHERE NOT EXISTS (SELECT 1
                  FROM Booking b
                  WHERE (dateFrom <= CURRENT_DATE AND dateTo >= CURRENT_DATE) AND
                        b.hotelNo = r.hotelNo and
                        b.roomNo = r.roomNo
                 )
GROUP BY hotelNo;

当然,您可以将其写为join,但即使使用join,也不需要hotel表:

SELECT r.hotelNo, SUM(r.price)
FROM Room r left join 
     Booking b 
     ON b.dateFrom <= CURRENT_DATE AND
        b.dateTo >= CURRENT_DATE and
        b.roomNo = r.roomNo and b.hotelNo = r.hotelNo
WHERE b.roomNo is null       
GROUP BY r.hotelNo; 

答案 1 :(得分:0)

如果我理解正确,这就是我要写的查询类型:

SELECT hotelNo, SUM(price) FROM Room r
left join 
    (SELECT roomNo , hotelNo
    FROM Booking b 
    join Hotel h ON  b.hotelNo = h.hotelNo
    WHERE dateFrom <= CURRENT_DATE AND
        dateTo >= CURRENT_DATE)  a
        ON a. roomNo = r.roomNo and a.hotelNo= r.hotelNo
 WHERE a.roomNo is null       
GROUP BY hotelNo;