【问题标题】:SQL -- many-to-many querySQL——多对多查询
【发布时间】:2016-12-01 16:21:11
【问题描述】:

我正在尝试选择所有包含给定数量成分的食谱。我可以根据一个给定的 recipe_id 找到所有食谱 与:

SELECT name
FROM recipe
INNER JOIN recipe_ingredient
ON recipe.recipe_id = recipe_ingredient.recipe_id
WHERE recipe_ingredient.recipe_id = ?

但是,当我在寻找包含不止一种特定成分的食谱时,我无法弄清楚查询应该是什么样子。例如成分 A 和成分 B。

我的表格如下所示:

ingredient
  -ingredient_id
  -name

recipe_ingredient
  -recipe_ingredient
  -ingredient_id
  -recipe_id


recipe
  -recipe_id
  -name

对于如何解决该问题的任何想法,我都会非常高兴! 谢谢。

【问题讨论】:

  • 这里有一个区别。您是否想要所有含有一种以上成分的食谱,而不管它们是哪种成分?还是您想要所有包含特定成分的食谱?从您的问题中不清楚,但有两个答案都涵盖了
  • 你说得对,我的问题还不够清楚。对此感到抱歉。我正在寻找所有包含特定成分的食谱!
  • 好的 - 我根据这条评论更新了我的答案

标签: mysql sql


【解决方案1】:

您的查询将如下所示

Your query will look something like this

SELECT name, count(*)
FROM recipe
INNER JOIN recipe_ingredient
ON recipe.recipe_id = recipe_ingredient.recipe_id
GROUP BY name 
HAVING count(*) > 1

【讨论】:

    【解决方案2】:

    如果要查找特定成分,您可以进行预查询,将您感兴趣的所有成分合并。将其加入到每个配方的成分表中,并确保所有成分都已计算在内。这由 group by 处理,并且 count = 您要查找的成分数量。

    我根据成分的名称做了这个例子。如果您有/知道实际的成分 ID(这会更准确,例如基于 Web 并且您有用户选择的 ID),只需将连接条件更改为成分 ID,而不仅仅是成分的描述。

    SELECT
          r.name,
          r.recipe_id
       from
          ( SELECT 'Milk' as Ingredient
               UNION select 'Eggs'
               UNION select 'Butter' ) as Wanted
             JOIN recipe_ingredient ri
                ON Wanted.Ingredient = ri.recipe_ingredient
                JOIN Recipe r
                   ON ri.Recipe_id = r.id
       group by
          ri.recipe_id
       having
          COUNT(*) = 3
    

    在这种情况下,牛奶、黄油、鸡蛋和最终计数 = 3。

    【讨论】:

      【解决方案3】:

      为了匹配IN 子句的所有 元素,您需要确保只选择count 与列表中成分总数匹配的食谱:

      SELECT name
      FROM recipe
      INNER JOIN recipe_ingredient
      ON recipe.recipe_id = recipe_ingredient.recipe_id
      WHERE recipe_ingredient.ingredient_id IN (ID1, ID2, ID3) --list of ingredient IDs
      Group By Name
      Having Count(*) = 3 --# of Ingredients you have chosen
      

      祝你好运,找到适合你可用原料的食谱

      Here is a functional example

      【讨论】:

      • 当我将最后一行 WHERE recipe_ingredient.recipe_id IN (ID1, ID2, ID3) 更改为 WHERE recipe_ingredient.ingredient_id IN (ID1, ID2, ID3) 时,它给了我所有包含至少一个给定 ID 的食谱!所以这对我来说是朝着正确方向迈出的一大步。但现在我的问题是如何获得那些至少包含所有给定成分的食谱,而不仅仅是给定成分的子集。
      • @ArtemisUser 感谢您指出它应该是ingredient_id。我刚刚更新了答案以确保您匹配列表中的所有元素
      【解决方案4】:

      只需将OR 用作您的where。 像这样

      $query = "SELECT name
      FROM recipe
      INNER JOIN recipe_ingredient
      ON recipe.recipe_id = recipe_ingredient.recipe_id
      WHERE recipe_ingredient.recipe_id = ? OR recipe_ingredient.recipe_id = ?";
      

      【讨论】:

        【解决方案5】:

        使用 group by 和 having 子句

        SELECT name
        FROM recipe
        INNER JOIN recipe_ingredient
        ON recipe.recipe_id = recipe_ingredient.recipe_id
        GROUP BY name
        HAVING count(1) > 1
        

        【讨论】:

        • 你的 group by 应该在名字上。我很确定这会引发书面错误
        • 是的,我也在想同样的事情,只是为了简化查询,谢谢:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多