简体   繁体   中英

SQL — many-to-many query

I'm trying to select all recipes which contain a given number of ingredients . I'm able to find all recipes based on one given recipe_id with:

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

But I'm having trouble figuring out what the query should look like when I'm looking for recipes which contain more than contain more than one specific ingredient . For Example Ingredient A and Ingredient B.

My tables look like this:

ingredient
  -ingredient_id
  -name

recipe_ingredient
  -recipe_ingredient
  -ingredient_id
  -recipe_id


recipe
  -recipe_id
  -name

I would be very happy about any ideas on how to solve that problem! Thanks.

Your query will look something like this

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

In order to match all elements of an IN clause, you need to make sure you select only Recipes that have a count which matches the total number of Ingredients in your list:

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

Good luck finding which recipe will work with the ingredients you have available

Here is a functional example

IF looking for specific Ingredients, you could do a pre-query doing a union of all the ingredients you are interested in. Join that to the ingredients table per recipe and make sure that all ingredients are accounted for. This is handled by the group by and having count = the number of ingredients you are looking for.

I did this example based on the name of the ingredient. If you have/know the actual ingredient ID (which would be more accurate such as web-based and you have the IDs chosen by a user), just change the join condition to the ingredient ID instead of just the description of the ingredient.

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

In this case, Milk, Butter, Eggs and a final count = 3.

Use group by and having clause

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

Just use OR for your where . Like this

$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 = ?";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM