I find my self lost while trying to create an actually pretty easy SQL statement.
I got a database with 3 Tables:
- recipes – storing some recipes names for cooking
- ingredients_recipes – links ingredients with recipes
- ingredients – the ingredients used by recipes.
its stored like this to make it double-clear:
recipes:
id | name 1 | lasagne alla bolognese 2 | tuna with tomatoes
ingredients:
id | name 1 | lasagne slices 2 | meat 3 | tomato 4 | tuna
and join-table ingredients_recipes:
ingredient_id | recipes_id
1 | 1
2 | 1
3 | 1
3 | 2
4 | 2
So as you can see, there are 2 really undelicios recipes which I should at least give some spices. But what I want to do before is selecting recipes by ingredients.
I want to have all my recipes having meat AND tomatoes:
SELECT recipes.name FROM recipes r
INNER JOIN ingredients_recipes ir ON ir.recipes_id = r.id
WHERE ir.ingredient_id IN ( 2 ) AND ir.ingredient_id IN ( 3 )
-> lasagna.. fine! (I use IN since there might be a bunch of ingredients, like “tomato”, “tomatoes”, “tomatoes, sliced” etc.. )
When I want to have e.g. all recipes having tomatoes but NOT having tuna, I tried:
SELECT recipes.name FROM recipes r
INNER JOIN ingredients_recipes ir ON ir.recipes_id = r.id
WHERE ir.ingredient_id IN ( 2 ) AND ir.ingredient_id NOT IN ( 4 )
-> still getting tuna – since one of the rows i join does not contain ingredient 4. okay :/
What I am wondering now is, what do I have to do, to get my desired results.
I currently put an arrow to my knee by doing a subselect like this:
SELECT recipes.name FROM recipes r
INNER JOIN ingredients_recipes ir ON ir.recipes_id = r.id
WHERE (
ir.ingredient_id IN ( 2 ) -- or more..
AND
recipes.id NOT IN ( SELECT recipes_id FROM ingredients_recipes
WHERE ingredient_id IN ( 4 ) -- actually i paste names of the ingredients.. but that is not the case. just to shorten the query.. by filling in a comment twice as long..
)
)
as I am quite new to mySQL, I don’t even know what to google for. so any help in that case, and o/c the better SQL statement would be ..
IN(awesome).
Edit: ah, and yes I actually do grouping.. 😉
This is one way. (untested)
The only way for count(*) to be 2 is if 2 and 3 ar both present.
Another way could be: (still untested)
UPDATE: (i had misread the question) If you also don’t want recipes with particular ingredients present you could add yet another subquery “leg” to the query: