MySQL从多对多关系枢轴

时间:2016-02-24 10:16:40

标签: mysql

我有三个表,productsingredientsingredient_product

我需要找到所有products,其中产品具有相关成分。 它还需要在percentage列上具有匹配值。

存在两种相关成分的产品。

+-----+------------+---------------+------------+
| id  | product_id | ingredient_id | percentage |
+-----+------------+---------------+------------+
|   1 |          1 |            1 |         50  |
|   2 |          1 |            2 |         50  |
+------------------+--------------+-------------+

要检索的SQL:

SELECT
      products.id
    FROM
      products,
      ingredient_product
    WHERE
        ingredient_product.product_id = products.id
    AND
        (ingredient_product.ingredient_id = 1 AND ingredient_product.percentage = 50)
    AND
        (ingredient_product.ingredient_id = 2 AND ingredient_product.percentage = 50)

但是这会返回一个空结果。 Empty set (0.00 sec)

产品:

+-------------------+-----------------------+------+-----+---------+----------------+
| Field             | Type                  | Null | Key | Default | Extra          |
+-------------------+-----------------------+------+-----+---------+----------------+
| id                | int(10) unsigned      | NO   | PRI | NULL    | auto_increment |
| name              | varchar(255)          | NO   |     | NULL    |                |
| short_description | text                  | YES  |     | NULL    |                |
| long_description  | text                  | YES  |     | NULL    |                |
+-------------------+-----------------------+------+-----+---------+----------------+

成分:

+-------------------+-----------------------+------+-----+---------+----------------+
| Field             | Type                  | Null | Key | Default | Extra          |
+-------------------+-----------------------+------+-----+---------+----------------+
| id                | int(10) unsigned      | NO   | PRI | NULL    | auto_increment |
| short_name        | varchar(50)           | NO   |     | NULL    |                |
| thumbnail         | varchar(255)          | NO   |     | NULL    |                |
+-------------------+-----------------------+------+-----+---------+----------------+

ingredient_product

+---------------+---------------------+------+-----+---------+----------------+
| Field         | Type                | Null | Key | Default | Extra          |
+---------------+---------------------+------+-----+---------+----------------+
| id            | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |
| product_id    | int(10) unsigned    | NO   | MUL | NULL    |                |
| ingredient_id | int(10) unsigned    | NO   | MUL | NULL    |                |
| percentage    | tinyint(3) unsigned | NO   |     | NULL    |                |
+---------------+---------------------+------+-----+---------+----------------+

2 个答案:

答案 0 :(得分:2)

基于草莓回答:

SELECT product_id 
FROM ingredient_product 
WHERE ingredient_id IN (1,2) AND percentage = 50
GROUP BY product_id 
HAVING COUNT(*) = 2;

但是,如果您需要单独的百分比,这不起作用,但您可以这样做:

SELECT product_id FROM
    (SELECT product_id 
    FROM ingredient_product 
    WHERE ingredient_id = 1 AND percentage = 50
    UNION ALL
    SELECT product_id 
    FROM ingredient_product 
    WHERE ingredient_id = 2 AND percentage = 50) AS tmp
GROUP BY product_id 
HAVING COUNT(*) = 2;

基本上,您为每个需求添加UNION(由id和百分比组合组成),然后将HAVING条件增加到需求数量。

注意:由于在这种情况下要求是互斥的,UNION ALLUNION更快,并且会给您相同的结果。

您可以使用UNION而不是子查询中的OR,但我们发现MySQL似乎更喜欢这种格式。然而,这可能会因版本而异。为了完整起见,这里也是解决方案:

SELECT product_id 
FROM ingredient_product 
WHERE (ingredient_id = 1 AND percentage = 50) OR (ingredient_id = 2 AND percentage = 50)
GROUP BY product_id 
HAVING COUNT(*) = 2;

答案 1 :(得分:0)

假设id是多余的,并且你有一个完全可维护的自然键(product_id,ingredient_id)......

SELECT product_id 
  FROM ingredient_product 
 WHERE ingredient_id IN (1,2) 
 GROUP 
    BY product_id 
HAVING COUNT(*) = 2;