Reputation: 79
I have the following 3 tables in my database, and am having some trouble querying them for the results I want. I'm trying to search for recipes by ingredients.
SQL Fiddle: Fiddle
Here are my tables: Ingredients
+---------------+---------+
| ingredient_id | name |
+---------------+---------+
| 1 | tomato |
| 2 | onion |
| 3 | rice |
| 4 | chicken |
| 5 | beef |
| 6 | noodles |
| 7 | salt |
+---------------+---------+
Recipes
+-----------+------------------+
| recipe_id | name |
+-----------+------------------+
| 1 | tomato goodness |
| 2 | meat deluxe |
| 3 | chicken surprise |
+-----------+------------------+
Ingredient_Index
+-----------+---------------+
| recipe_id | ingredient_id |
+-----------+---------------+
| 1 | 1 |
| 1 | 5 |
| 1 | 7 |
| 2 | 5 |
| 2 | 6 |
| 2 | 7 |
| 3 | 4 |
| 3 | 3 |
| 3 | 7 |
+-----------+---------------+
What I would like to achieve, Is to filter all recipes I can make using specified ingredients. And here comes the problem:
This query:
select DISTINCT r.name
from
recipes r
inner join ingredient_index i
on i.recipe_id = r.recipe_id
where i.ingredient_id IN (2, 7, 5);
Gives me false results, because I don't have enough ingredients to make any of recipes, yet still I get a result that I can make all of them. That happens because recipe_id is duplicating in Ingredient_Index table.
Any help would me much appreciated.
Upvotes: 2
Views: 1163
Reputation: 7240
As jarlh said, check no ingredient missing:
select DISTINCT r.name
from recipes r
where not exists (
select 1 from ingredient_index i where r.recipe_id=i.recipe_id and i.ingredient_id not in (2,5,7)
)
Upvotes: 2
Reputation: 44766
Another way:
select r.name
from recipes r
join ingredient_index i on i.recipe_id = r.recipe_id
where i.ingredient_id IN (2, 7, 5)
group by r.name
having count(i.ingredient_id) = 3
Upvotes: 0
Reputation: 9568
Mine follows the other suggestion jarlh gave, and checks whether all ingredients are available:
select distinct a.name
from (select r.name, count(*) as ing_available
from
recipes r
inner join ingredient_index i
on i.recipe_id = r.recipe_id
where i.ingredient_id IN (1, 7, 5)
group by r.recipe_id)
as a join
(select r.name, count(*) as ing_required
from
recipes r
inner join ingredient_index i
on i.recipe_id = r.recipe_id
group by r.recipe_id)
as p
on p.ing_required = a.ing_available
Upvotes: 0