Reputation: 2371
I have this schema:
Hotel (**hotelNo**, hotelName, city)
Room (**roomNo, hotelNo**, type, price)
Booking (**hotelNo, guestNo, dateFrom**, dateTo, roomNo)
Guest (**guestNo**, guestName, guestAddress)
** denotes primary keys
I have to complete this query:
I have this query, which isn't quite correct:
SELECT r.hotelno, type, count(*)
FROM Hotel h, room r
WHERE h.hotelNo = r.hotelno
GROUP BY r.hotelNo, type;
This is what it outputs:
What am I doing wrong?
Upvotes: 1
Views: 259
Reputation: 753485
It looks as though you're seeking the type of room which has maximum number of bookings for rooms of a given type at each hotel - an aggregate (maximum) of another aggregate (count of bookings of room type).
Build it up piece-wise. The number of bookings of rooms of each type at each hotel:
SELECT r.hotelno, r.type, count(*) AS num_bookings
FROM Booking AS b
JOIN Room AS r ON b.hotelNo = r.hotelno AND b.roomNo = r.roomNo
GROUP BY r.hotelNo, r.type;
Now, you need to know which room type has the maximum at each hotel. That has to be done in two stages:
The first stage is:
SELECT s.hotelno, MAX(num_bookings) AS max_bookings
FROM (SELECT r.hotelno, r.type, count(*) AS num_bookings
FROM Booking AS b
JOIN Room AS r ON b.hotelNo = r.hotelno AND b.roomNo = r.roomNo
GROUP BY r.hotelNo, r.type
) AS s
GROUP BY s.hotelno;
The second stage uses both the previous results for a final answer:
SELECT t.hotelno, t.type
FROM (SELECT r.hotelno, r.type, count(*) AS num_bookings
FROM Booking AS b
JOIN Room AS r ON b.hotelNo = r.hotelno AND b.roomNo = r.roomNo
GROUP BY r.hotelNo, r.type) AS t
JOIN (SELECT s.hotelno, MAX(num_bookings) AS max_bookings
FROM (SELECT r.hotelno, r.type, count(*) AS num_bookings
FROM Booking AS b
JOIN Room AS r ON b.hotelNo = r.hotelno AND b.roomNo = r.roomNo
GROUP BY r.hotelNo, r.type
) AS s
GROUP BY s.hotelno) AS m
ON t.hotelno = m.hotelno AND t.num_bookings = m.max_bookings;
If your DBMS supports WITH clauses, you can write that more succinctly.
Upvotes: 1
Reputation: 8693
I think you're going to have to use an inner query to get this one working:
SELECT dbo.Hotel.hotelName, pop.type, pop.Count
FROM dbo.Hotel
INNER JOIN (
SELECT TOP 1 dbo.Hotel.hotelNo, dbo.Room.type, COUNT(*) AS Count
FROM dbo.Hotel
INNER JOIN dbo.Room ON dbo.Room.hotelNo = dbo.Hotel.hotelNo
INNER JOIN dbo.Booking ON dbo.Booking.roomNo = dbo.Room.roomNo AND dbo.Booking.hotelNo = dbo.Hotel.hotelNo
GROUP BY dbo.Hotel.hotelNo, dbo.Room.type
ORDER BY Count DESC, dbo.Room.type
) AS pop ON pop.hotelNo = dbo.Hotel.HotelNo
ORDER BY dbo.Hotel.hotelName
Upvotes: 0
Reputation: 16757
If you are looking for popularity, you would need to take into account the Booking table. Add the Booking table to your FROM statement, link on hotelNo and roomNo and do a count on the Booking table. This should give you the counts you want.
Edit: Here is some sample code for you (tested):
SELECT TOP (100) PERCENT dbo.Hotel.hotelName, dbo.Room.type, COUNT(*) AS Count
FROM dbo.Booking INNER JOIN
dbo.Room ON dbo.Booking.roomNo = dbo.Room.roomNo AND dbo.Booking.hotelNo = dbo.Room.hotelNo
INNER JOIN dbo.Hotel ON dbo.Room.hotelNo = dbo.Hotel.hotelNo
GROUP BY dbo.Hotel.hotelName, dbo.Room.type
ORDER BY Count DESC
Upvotes: 1