mysql - 高级 SELECT 查询 (HAVING)

标签 mysql select having

我有以下理论数据库:

酒店(Hotel_No、姓名、地址)
房间(Room_No, Hotel_No, Type, Price)
预订(Hotel_NoGuest_NoDate_From,Date_To,Room_No)
客人(客人编号,姓名,地址)

粗体属性用作该表的主键。

目标是为伦敦的每家酒店找到最常预订的房型。我脑海中预期的最终输出如下,其中 Hotel_No 是伦敦一家独特酒店的 ID,Type 是酒店提供的房间类型:

+----------+----------+-------+
| Hotel_No |   Type   | Count |
+----------+----------+-------+
|       67 | Single   |    53 |
|       45 | Double   |    67 |
|       32 | Double   |    23 |
|      ... | ...      |   ... |
+----------+----------+-------+

预订被计为预订表中的预订,每一行代表一个预订。

我得到的答案如下:

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);

这个解决方案是否正确?

我无法理解嵌套查询如何设法选择伦敦酒店预订的最高类型,而不是简单地返回按类型预订最高的一行或多行,汇总伦敦的所有酒店。

为什么我们在嵌套查询、B2、R2中新建了一张表,却仍然引用了原来的H表?

示例数据:

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);

最佳答案

解决方案看起来不错,在主要查询中,您的表按酒店和类型加入并分组,我相信类型来自房间表,基于此分组,您可以获得每个酒店和房间类型的预订数量,这可能会给您更多每家酒店多排取决于酒店所属房型的预订情况。

子查询部分只是从上面的查询中挑选出每家酒店计数最高的行,所以如果酒店 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(*) DESCLIMIT 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,而如果您在下一列中看到子查询的结果,则两行的计数为 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 条不同房间类型的记录,因为它们都有相同的最高计数

DEMO

关于mysql - 高级 SELECT 查询 (HAVING),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47902093/

相关文章:

mysql - 选择两周前的查询

java - 具有空兴趣集的 SelectionKey

mysql - 如何在mysql查询中使用一个或多个OR和AND

Mysql - 排除计数>值但显示所有行

mysql - ZF2 + Doctrine Entity - 将查询作为带有日期时间对象的数组返回?

mysql - MySQL 加入问题

mysql - 这个 if/then 存储过程有什么问题?

mySQL 具有排除优化

MySQL GROUP BY 和 HAVING

mysql - Laravel 支持哪些数据库以及如何添加另一个数据库?