2

我对 SQL 查询感到困惑,需要您的帮助。简单地说,我需要退回所有提供包含我选择的所有项目的套餐的酒店

涉及的表格有:

  • 酒店(hotel_id,hotel_name)
  • (package_id、hotel_id、package_name)
  • 项目(item_id、package_id、item_name)
  • package_items (package_id, item_id)

样本数据

为了帮助解释我的问题,让我们看一下这个示例数据以更清楚地说明它。

酒店表

----------------------
hotel_id | 酒店名称
----------------------
1 | 希尔顿
2 | 威斯汀
----------------------

包表

-----------------------------------------
package_id | hotel_id | 包裹名字
-----------------------------------------
1 | 1 | 黄金套餐
2 | 1 | 银包
3 | 2 | 明星套餐
4 | 2 | 终极套餐
-----------------------------------------

项目表

-------------------------------------------
item_id | 项目名称
-------------------------------------------
1 | 免费客房升级
2 | 含晚餐
3 | 水疗中心
4 | 免费论文
-------------------------------------------

包裹项目表

---------------------
package_id | item_id
---------------------
1 | 2
1 | 3
1 | 4
2 | 2
2 | 3
3 | 4
4 | 1
4 | 2
4 | 3
4 | 4
---------------------

因此,使用此数据您可以看到,例如,希尔顿的黄金套餐包含晚餐、水疗中心和免费文件。

我正在我们的前端构建一个功能,让用户过滤这些不同的包项目。每个项目的复选框,单击该复选框应过滤结果以仅显示提供包含用户选择的所有项目的套餐的酒店。

为此,我对 SQL 有点困惑。到目前为止,我的研究已经将我带到了以下示例代码(在这里找到:PostgreSQL where all in array):

SELECT conversation_id FROM conversations_users

 WHERE user_id IN (1,2)

 GROUP BY conversation_id HAVING COUNT(*) = 2

在此示例查询中,查询的关键部分是 HAVING COUNT( ) = 2 部分。有了这个,我希望强制查询以确保必须匹配所有选定的项目,而不仅仅是一个,这是没有 HAVING COUNT( ) = 2 部分的查询的默认行为。

使用这种方法和上面的表格结构,我已经调整了这个代码以满足我们自己的要求,包括各种 JOIN 查询等。在下面的示例中,我选择了包含晚餐、水疗中心和免费论文。我希望能回到希尔顿和威斯汀酒店,因为这两家酒店都提供包含所有这些项目的套餐。在希尔顿的情况下,他们的黄金套餐提供了我选择的内容,而在威斯汀的情况下,他们的终极套餐提供了我选择的内容。

请记住,我正在尝试查找提供包含我正在搜索的所有项目的套餐的酒店。

这是我到目前为止所得到的:

SELECT h.hotel_id, h.hotel_name FROM hotels h

  JOIN packages p       ON h.hotel_id   = p.hotel_id
  JOIN package_items pi ON p.package_id = pi.package_id
  JOIN items i          ON pi.item_id   = i.item_id

 WHERE i.item_id IN (2,3,4)

 GROUP BY h.hotel_id HAVING COUNT (*) = 3;

不幸的是,我在这里没有得到准确的结果,我不知道如何解决它。对任何可以为我解决这个问题的人表示深深的敬意。

4

2 回答 2

3

将您的最后一个查询更新为:

     SELECT h.hotel_id, h.hotel_name FROM hotels h
     JOIN packages p       ON h.hotel_id   = p.hotel_id
     JOIN package_items pi ON p.package_id = pi.package_id
     JOIN items i          ON pi.item_id   = i.item_id
     WHERE i.item_id IN (2,3,4)
     GROUP BY h.hotel_id 
     HAVING COUNT (DISTINCT i.item_id) = 3;

这将为您返回包含 3 种不同项目的酒店。

于 2012-11-10T14:56:19.330 回答
1

将 package_name 添加到分组中...如下所示,将其放在初始 SELECT 中以显示它的工作原理

SELECT h.hotel_id, h.hotel_name, p.package_name FROM hotels h
  JOIN packages p       ON h.hotel_id   = p.hotel_id
  JOIN package_items pi ON p.package_id = pi.package_id
  JOIN items i          ON pi.item_id   = i.item_id
 WHERE i.item_id IN (2,3,4)
 GROUP BY h.hotel_name, p.package_name  HAVING COUNT(*) = 3;

+----------+------------+------------------+
| hotel_id | hotel_name | package_name     |
+----------+------------+------------------+
|        1 | Hilton     | Gold Package     |
|        2 | Weston     | Ultimate Package |
+----------+------------+------------------+
于 2012-11-10T16:20:13.430 回答