高级 SELECT 查询 (HAVING)
Advanced SELECT query (HAVING)
我有以下理论数据库:
酒店(Hotel_No,姓名,地址)
房间(Room_No,Hotel_No,类型,价格)
预订(Hotel_No,Guest_No,Date_From, Date_To, Room_No)
客人(Guest_No,姓名,地址)
粗体属性用作 table 的主键。
目标是为伦敦的每家酒店找到最常预订的房型。我脑海中预期的最终输出如下,其中 Hotel_No
是伦敦一家独特酒店的 ID,Type
是酒店提供的房间类型:
+----------+----------+-------+
| Hotel_No | Type | Count |
+----------+----------+-------+
| 67 | Single | 53 |
| 45 | Double | 67 |
| 32 | Double | 23 |
| ... | ... | ... |
+----------+----------+-------+
预订被计为预订中的预订table,每一行代表一个预订。
我得到的答案如下:
SELECT Type, H.hotel No
FROM Room R, Hotel H, Booking B
WHERE R.Hotel_No = H.Hotel No
AND H.Address LIKE '%London%'
AND B.Room No = R.Room_No
AND H.Hotel_No = B.Hotel_No
GROUP BY Type, H.hotel_No
HAVING Count(*) >= ALL(
SELECT Count(*)
FROM Booking B2,Room R2
WHERE B2.Hotel_No = H.Hotel_No
AND R2.Room_No = B2.Room_No
GROUP BY R2.Type);
这个解决方案是否正确?
我无法理解嵌套查询如何管理 select 伦敦酒店的最高酒店预订类型,而不是简单地返回具有最高预订类型的一行或多行,汇总伦敦的所有酒店。
为什么我们在嵌套查询、B2、R2中新建了table,却仍然引用原来的Htable?
示例数据:
CREATE TABLE Hotel (
Hotel_No INT NOT NULL AUTO_INCREMENT,
Hotel VARCHAR(10),
Address VARCHAR(10),
PRIMARY KEY (Hotel_No)
);
CREATE TABLE Room (
Room_No INT NOT NULL,
Hotel_No INT NOT NULL,
Type ENUM('Single', 'Double', 'Family'),
PRIMARY KEY(Room_No, Hotel_No),
FOREIGN KEY(Hotel_No) REFERENCES Hotel(Hotel_No)
);
CREATE TABLE Booking (
Hotel_No INT NOT NULL,
Guest_No INT NOT NULL,
Date_From DATE NOT NULL,
Room_No INT NOT NULL,
PRIMARY KEY (Hotel_No, Guest_No, Date_From),
FOREIGN KEY (Hotel_No) REFERENCES Hotel(Hotel_No),
FOREIGN KEY (Room_No, Hotel_No) REFERENCES Room(Room_No, Hotel_No)
);
INSERT INTO Hotel (Name, Address) VALUES
('Hotel A', 'London'),
('Hotel B', 'London'),
('Hotel C', 'London'),
('Hotel D', 'Birmingham');
INSERT INTO Room VALUES
(1, 1, 'Single'),
(2, 1, 'Double'),
(1, 2, 'Single'),
(2, 2, 'Double'),
(3, 2, 'Family'),
(1, 3, 'Single'),
(2, 3, 'Double'),
(1, 4, 'Single'),
(2, 4, 'Single');
INSERT INTO Booking VALUES
(1, 1, '2000/01/01', 1),
(1, 2, '2000/02/01', 1),
(1, 3, '2000/01/01', 2),
(1, 4, '2000/02/01', 2),
(1, 5, '2000/03/01', 2),
(2, 6, '2000/01/01', 1),
(2, 7, '2000/01/01', 2),
(2, 8, '2000/01/01', 3),
(2, 9, '2000/02/01', 3),
(2, 11, '2000/01/01', 1),
(3, 12, '2000/01/01', 2),
(3, 13, '2000/02/01', 2);
解决方案看起来不错,在主查询中,您的 table 已按酒店和类型加入并分组,我相信类型来自房间 table,基于此分组,您可以获得每个酒店和房间类型的预订可能会为您提供超过一行的每个酒店,具体取决于属于酒店的房间类型的预订。
子查询部分只是从上面的查询中挑选出每家酒店计数最高的行,所以如果酒店 A 有以下计数
A single 10
A double 15
然后酒店 A 将返回第二行,因为它的计数最高。每家酒店都采用相同的逻辑。
Edit for sample data
我已经调整了您发布的查询,以获取最大数量的酒店和房型,如下所示。
SELECT TYPE, H.hotel_No,COUNT(*)
FROM Room R, Hotel H, Booking B
WHERE R.Hotel_No = H.Hotel_No
AND H.Address LIKE '%London%'
AND B.Room_No = R.Room_No
AND H.Hotel_No = B.Hotel_No
GROUP BY TYPE, H.hotel_No
HAVING COUNT(*) >= (
SELECT COUNT(*)
FROM Booking B2,Room R2
WHERE B2.Hotel_No = H.Hotel_No
AND R2.Room_No = B2.Room_No
AND R2.Hotel_No = H.Hotel_No
GROUP BY R2.Type
ORDER BY COUNT(*) DESC
LIMIT 1)
ORDER BY H.hotel_No
原来的相关子查询丢失了另一个匹配过滤器 R2.Hotel_No = H.Hotel_No
然后 ORDER BY COUNT(*) DESC
和 LIMIT 1
以获得每家酒店的最高计数,如果是'如果不使用,您将没有数据,因为与按酒店和房间类型预订的数量相比,不包括房间类型的预订数量会更高。
所以回到这里的问题是子查询在做什么。父查询的每一行都可以看到子查询的结果here
TYPE hotel_No COUNT(*) sub_query
------ -------- -------- -----------
Single 1 2 3
Double 1 3 3
Single 2 2 2
Double 2 1 2
Family 2 2 2
Double 3 2 2
在上面,您可以看到对于酒店 1,有 2 行房间类型单人预订数量为 2,房间类型双人预订数量为 3,如果您在下一列中看到 sub_query 的结果两行的计数为 3。因此,如果您逐个比较酒店 1 的计数和子查询结果,第一行将被排除,因为单个预订计数小于最大计数。其他行的逻辑相同。
最终结果集
TYPE hotel_No COUNT(*)
1 Double 1 3
2 Single 2 2
3 Family 2 2
4 Double 3 2
在最终结果集中,您可以看到酒店 ID 2 有 2 条不同房间类型的记录,因为它们都有相同的最高计数
我有以下理论数据库:
酒店(Hotel_No,姓名,地址)
房间(Room_No,Hotel_No,类型,价格)
预订(Hotel_No,Guest_No,Date_From, Date_To, Room_No)
客人(Guest_No,姓名,地址)
粗体属性用作 table 的主键。
目标是为伦敦的每家酒店找到最常预订的房型。我脑海中预期的最终输出如下,其中 Hotel_No
是伦敦一家独特酒店的 ID,Type
是酒店提供的房间类型:
+----------+----------+-------+
| Hotel_No | Type | Count |
+----------+----------+-------+
| 67 | Single | 53 |
| 45 | Double | 67 |
| 32 | Double | 23 |
| ... | ... | ... |
+----------+----------+-------+
预订被计为预订中的预订table,每一行代表一个预订。
我得到的答案如下:
SELECT Type, H.hotel No
FROM Room R, Hotel H, Booking B
WHERE R.Hotel_No = H.Hotel No
AND H.Address LIKE '%London%'
AND B.Room No = R.Room_No
AND H.Hotel_No = B.Hotel_No
GROUP BY Type, H.hotel_No
HAVING Count(*) >= ALL(
SELECT Count(*)
FROM Booking B2,Room R2
WHERE B2.Hotel_No = H.Hotel_No
AND R2.Room_No = B2.Room_No
GROUP BY R2.Type);
这个解决方案是否正确?
我无法理解嵌套查询如何管理 select 伦敦酒店的最高酒店预订类型,而不是简单地返回具有最高预订类型的一行或多行,汇总伦敦的所有酒店。
为什么我们在嵌套查询、B2、R2中新建了table,却仍然引用原来的Htable?
示例数据:
CREATE TABLE Hotel (
Hotel_No INT NOT NULL AUTO_INCREMENT,
Hotel VARCHAR(10),
Address VARCHAR(10),
PRIMARY KEY (Hotel_No)
);
CREATE TABLE Room (
Room_No INT NOT NULL,
Hotel_No INT NOT NULL,
Type ENUM('Single', 'Double', 'Family'),
PRIMARY KEY(Room_No, Hotel_No),
FOREIGN KEY(Hotel_No) REFERENCES Hotel(Hotel_No)
);
CREATE TABLE Booking (
Hotel_No INT NOT NULL,
Guest_No INT NOT NULL,
Date_From DATE NOT NULL,
Room_No INT NOT NULL,
PRIMARY KEY (Hotel_No, Guest_No, Date_From),
FOREIGN KEY (Hotel_No) REFERENCES Hotel(Hotel_No),
FOREIGN KEY (Room_No, Hotel_No) REFERENCES Room(Room_No, Hotel_No)
);
INSERT INTO Hotel (Name, Address) VALUES
('Hotel A', 'London'),
('Hotel B', 'London'),
('Hotel C', 'London'),
('Hotel D', 'Birmingham');
INSERT INTO Room VALUES
(1, 1, 'Single'),
(2, 1, 'Double'),
(1, 2, 'Single'),
(2, 2, 'Double'),
(3, 2, 'Family'),
(1, 3, 'Single'),
(2, 3, 'Double'),
(1, 4, 'Single'),
(2, 4, 'Single');
INSERT INTO Booking VALUES
(1, 1, '2000/01/01', 1),
(1, 2, '2000/02/01', 1),
(1, 3, '2000/01/01', 2),
(1, 4, '2000/02/01', 2),
(1, 5, '2000/03/01', 2),
(2, 6, '2000/01/01', 1),
(2, 7, '2000/01/01', 2),
(2, 8, '2000/01/01', 3),
(2, 9, '2000/02/01', 3),
(2, 11, '2000/01/01', 1),
(3, 12, '2000/01/01', 2),
(3, 13, '2000/02/01', 2);
解决方案看起来不错,在主查询中,您的 table 已按酒店和类型加入并分组,我相信类型来自房间 table,基于此分组,您可以获得每个酒店和房间类型的预订可能会为您提供超过一行的每个酒店,具体取决于属于酒店的房间类型的预订。
子查询部分只是从上面的查询中挑选出每家酒店计数最高的行,所以如果酒店 A 有以下计数
A single 10
A double 15
然后酒店 A 将返回第二行,因为它的计数最高。每家酒店都采用相同的逻辑。
Edit for sample data
我已经调整了您发布的查询,以获取最大数量的酒店和房型,如下所示。
SELECT TYPE, H.hotel_No,COUNT(*)
FROM Room R, Hotel H, Booking B
WHERE R.Hotel_No = H.Hotel_No
AND H.Address LIKE '%London%'
AND B.Room_No = R.Room_No
AND H.Hotel_No = B.Hotel_No
GROUP BY TYPE, H.hotel_No
HAVING COUNT(*) >= (
SELECT COUNT(*)
FROM Booking B2,Room R2
WHERE B2.Hotel_No = H.Hotel_No
AND R2.Room_No = B2.Room_No
AND R2.Hotel_No = H.Hotel_No
GROUP BY R2.Type
ORDER BY COUNT(*) DESC
LIMIT 1)
ORDER BY H.hotel_No
原来的相关子查询丢失了另一个匹配过滤器 R2.Hotel_No = H.Hotel_No
然后 ORDER BY COUNT(*) DESC
和 LIMIT 1
以获得每家酒店的最高计数,如果是'如果不使用,您将没有数据,因为与按酒店和房间类型预订的数量相比,不包括房间类型的预订数量会更高。
所以回到这里的问题是子查询在做什么。父查询的每一行都可以看到子查询的结果here
TYPE hotel_No COUNT(*) sub_query
------ -------- -------- -----------
Single 1 2 3
Double 1 3 3
Single 2 2 2
Double 2 1 2
Family 2 2 2
Double 3 2 2
在上面,您可以看到对于酒店 1,有 2 行房间类型单人预订数量为 2,房间类型双人预订数量为 3,如果您在下一列中看到 sub_query 的结果两行的计数为 3。因此,如果您逐个比较酒店 1 的计数和子查询结果,第一行将被排除,因为单个预订计数小于最大计数。其他行的逻辑相同。
最终结果集
TYPE hotel_No COUNT(*)
1 Double 1 3
2 Single 2 2
3 Family 2 2
4 Double 3 2
在最终结果集中,您可以看到酒店 ID 2 有 2 条不同房间类型的记录,因为它们都有相同的最高计数