高级SELECT查询(HAVING)

时间:2017-12-20 08:55:26

标签: mysql select having

我有以下理论数据库:

酒店( Hotel_No ,姓名,地址)
    房间( Room_No Hotel_No ,类型,价格)
    预订( Hotel_No Guest_No Date_From ,Date_To,Room_No)
    访客( Guest_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);

1 个答案:

答案 0 :(得分:1)

解决方案看起来很好,在主查询中你的表被加入并按酒店和类型分组我相信类型来自房间表,根据这个分组,你可以得到每个酒店和房间类型的预订数量,这可能会给你更多每家酒店超过一排取决于预订属于酒店的房型。

子查询部分只是从上面的查询中选择具有每个酒店最高计数的行,所以如果酒店A有以下计数

A single 10
A double 15

然后酒店A将返回第二行,因为它的计数最高。每个酒店都有相同的逻辑。

  

编辑样本数据

我已经调整了您发布的查询,以获得最大数量的酒店和房间类型,如下所示。

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,以获得每个酒店的最高统计数。如果不是&n使用过你将没有数据,因为除了房间类型的预订数量将高于每个酒店和房间类型的预订数量。

这里回答问题是子查询正在做什么。对于父查询的每一行,可以看到子查询的结果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个不同房型的记录,因为它们共享相同的最高计数

DEMO