2015-02-06 94 views
1

鑑於這種模式:Group By子句是否需要加入?

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,然後計算出的價格與group by子句剩下的房間 - 我米甚至不知道它會工作,但在紙上看起來有效)。但是,看看示例解決方案:

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基於b.hotelNo=h.hotelNo加入這兩個關係,但查看架構,Booking提供了RoomNo(已預訂)的詳細信息,並提供關於哪個酒店和日期的信息......當然,這是我們需要處理的所有信息一個Group By子句並實現我們想要的結果?還是我誤會了?

+3

首先從未使用隱式連接;他們是一種SQL反模式。 – HLGEM 2015-02-06 20:22:32

+0

如果多家酒店的房間號碼相同,根據我的經驗,您的查詢沒有任何意義。實際上,您的表格結構沒有任何意義,除非您將RoomNo和HotelNo用作Room表格中的複合PK。 – HLGEM 2015-02-06 20:29:48

+0

@HLGEM感謝您的提示。我會考慮到這一點(儘管這直接來自答卷)。我還在我的模式中添加了鍵,是的,Room是一個複合鍵。 – gudthing 2015-02-06 20:37:35

回答

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; 
+0

Gordon非常感謝你的答案(這不是你第一次幫助我今晚!),出於好奇,三者中哪一個會被認爲是更好的解決方案?是否有任何顯着的性能差異? – gudthing 2015-02-06 21:13:23

+1

@ gudthing ......在這種情況下,第二個或第三個是「更好的」,在SQL中,當子查詢返回NULL時,NOT IN會表現異常。儘管你首先學習'NOT IN',但閱讀時更有意義,但這可能是危險的。出於這個原因,我主張使用'NOT EXISTS'或明確的'join'。順便說一下,您似乎對SQL和數據庫有很好的掌握;你需要更高級的課程。 – 2015-02-06 23:23:42

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; 
+0

如果Booking關係已經有'hotelNo',爲什麼我們需要加入與酒店的Booking關係?如果我們用'Hotel'離開了參加會議並且剛剛做了'r.hotelNo = b.hotelNo',會發生什麼? – gudthing 2015-02-06 20:46:24

+0

因爲您想要爲每個酒店都沒有預訂房間。酒店a可能有1,2,3間客房,B酒店可能預訂有2,4,6間客房。因此,你需要爲酒店b的房間4,5,6,7以及1,3,7房間的酒店提供總和。酒店和房間號碼都需要得到正確的結果。 – HLGEM 2015-02-06 20:52:50