Reputation: 400
I’m trying to join 3 tables in MySQL, and need some help.
My first table is a list of recipes.
**recipes**
RecipeID | RecipeName
1 | Cheese and Ham Toasty
2 | 20 Minute Pasta
3 | Minute Steak
The second table is a list of ingredients assign to the recipes table
**ingredients**
RecipeID | IngredientID | IngredientName
1 | 1 | Cheese
1 | 2 | Bread
1 | 3 | Ham
1 | 4 | Butter
2 | 5 | Pasta
2 | 6 | Mince
2 | 1 | Cheese
3 | 8 | Steak
3 | 9 | BBQ Sauce
The third table is a table that users can use to add ingredients they don’t want to see recipes of, for now only one ingredient for the user
**usersList**
IngredientID | userID
1 | 2
And my result when joining the tables should be as follows:
**recipes**
RecipeID | RecipeName
3 | Minute Steak
However my result is either all the recipes I don’t want or an empty result. Below is the MySQL that I’m using that currently supplies me with all the recipes I don’t want.
SELECT RecipeID, RecipeName FROM recipes LEFT JOIN ingredients
INNER JOIN usersList ON ingredients.IngredientID = usersList.IngredientID
ON recipes.RecipeID = ingredients.RecipeID
WHERE recipes.RecipeID IS NOT NULL
AND usersList.userID = 2
GROUP BY recipes.RecipeID
How can I join these tables so that I get all recipes that don’t include any of the recipes that have ingredients in the user list and still supplies results if the user has no ingredients listed? Thanks in advance for helping.
Upvotes: 2
Views: 41
Reputation: 3429
You can also use a left join here as follows:
select r.RecipeID, r.RecipeName from recipes r
left join (select RecipeID from ingredients i
join usersList u on u.RecipeID = i.RecipeID) as u
on u.RecipeID = r.RecipeID
where u.RecipeID is null
Upvotes: 0
Reputation: 94894
You are not looking for a join. You want to see recipes for which not exists a certain ingrediant. So select from the recipes table and limit the results with NOT EXISTS
or NOT IN
in the WHERE
clause. Here is a simple solution with two IN
clauses:
select *
from recipes
where recipeid not in
(
select recipeid
from ingredients
where ingredientid in
(
select ingredientid
from userslist
where userid = 2
)
);
Upvotes: 3
Reputation: 48357
Use an inner join between recipes and ingredients, a left join between ingredients and userlists, then in the exclude results where the Primary key returned from the userlist is not null.
The output of this will include multiple entries for recipes with multiple ingredients - which may need tidying....
SELECT recipename, GROUP_CONCAT(ingredient_name),
SUM(IF(userlist.ingredientid IS NULL, 0, 1))
FROM recipes
INNER JOIN ingredients
ON recipes.recipeid=ingredients.ingredientid
LEFT JOIN userlist
ON ingredients.ingredientid=userlist.ingredientid
AND userlist.userid=_______
GROUP BY recipename
HAVING SUM(IF(userlist.ingredientid IS NULL, 0, 1))=0
Upvotes: 0