SQL:多对多关系和“ALL”子句

Kug*_*itz 5 mysql sql relational-division

我有一个表products和一个表locations,它们以多对多关系与 table 链接在一起products_locations。现在,客户可以选择一组产品,我想运行一个查询,仅选择所有选定产品均可用的位置。

乍一看这似乎很简单,但我发现自己对如何实现这一目标感到非常困惑。我最初以为我可以用类似的东西获得所有正确的位置ID

SELECT location_id
FROM products_locations
WHERE product_id = ALL [the user selected product ids]
Run Code Online (Sandbox Code Playgroud)

但转念一想,这似乎也没有意义( 的结构products_locations非常简单[product_id, location_id]。

任何有关如何构建此类查询的建议将不胜感激。我觉得我忽略了一些基本的东西..

编辑:我正在使用mysql语法/方言

快速示例:给出下表

| products   | | locations | | products_locations       |
| id | name  | | id | name | | product_id | location_id |
|------------| |-----------| |--------------------------|
| 1  | prod1 | | 1  | locA | | 1          | 2           |
| 2  | prod2 | | 2  | locB | | 2          | 1           |
| 3  | prod3 | |-----------| | 2          | 2           |
|------------|               | 3          | 1           |
                             |--------------------------|
Run Code Online (Sandbox Code Playgroud)

如果用户选择产品 1 和 2,则查询应仅返回位置 2。如果用户选择产品 2 和 3,查询应返回位置 1。对于 1、2 和 3,没有位置有效,对于产品2、两个位置都有效。

Kug*_*itz 3

我想出了一个可以实现我需要的查询。尽管它并不像我希望的那么干净,但它似乎是解决我想要查询的问题的一种可靠方法:

SELECT t.location_id
FROM (SELECT location_id, COUNT(*) as n_hits
      FROM products_locations
      WHERE product_id IN [the user selected products]
      GROUP BY location_id) t
WHERE n_hits = [the number of user selected products];
Run Code Online (Sandbox Code Playgroud)

解释:

  1. 我创建一个临时表t,其中包含location_id用户选择中至少有一个匹配产品的每个表,以及该位置与用户选择中的产品匹配的次数。这是通过按 分组查询来实现的location_id。
  2. location_id我从该临时表中选择(s) t,其中点击数等于用户选择的产品数。如果该数字较低,我就知道至少有一种产品与该位置不匹配。