Reputation: 181
Let's say I have three tables (mysql):
recipes
+----+----------------+--------------+
| id | title | image |
+----+----------------+--------------+
| 2 | recipe title 1 | banana image |
| 3 | recipe title 2 | potato image |
+----+----------------+--------------+
ingredient
+----+-----------+---------+---------------+
| id | recipe_id | food_id | quantity_kg |
+----+-----------+---------+---------------+
| 1 | 2 | 36 | 2.5 |
| 2 | 3 | 37 | 1.5 |
+----+-----------+---------+---------------+
food
+----+---------+-------+-----------+----------+
| id | name | price | foodType | unitType |
+----+---------+-------+-----------+----------+
| 36 | carrot | 2 | vegetable | kg |
| 37 | chicken | 12 | meat | kg |
+----+---------+-------+-----------+----------+
Now, I want to get all the recipes that are vegetarian, i.e. that don't contain any foods where foodType is 'meat' (or other animal product).
How do I perform such query?
Here is what I've tried so far:
SELECT
recipe.id as recipeId,
recipe.title as title,
food.type as foodType
FROM recipe
INNER JOIN ingredient on ingredient.recipe_id = recipe.id
INNER JOIN food on food.id = ingredient.aliment_id
HAVING
food.type <> 'meat' AND
food.type <> 'seafood' AND
food.type <> 'fish'
ORDER BY recipeId
This works (I get only vegetarian recipes) BUT it duplicates all the recipes, as long as they have multiple ingredients. eg. :
+----------+--------+----------+
| recipeId | title | foodType |
+----------+--------+----------+
| 5 | titleA | type1 |
| 5 | titleA | type2 |
| 5 | titleA | type3 |
| 8 | titleB | type2 |
| 8 | titleB | type5 |
| 8 | titleB | type1 |
| 8 | titleB | type3 |
+----------+--------+----------+
What I want to obtain is:
+----------+--------+
| recipeId | title |
+----------+--------+
| 5 | titleA |
| 8 | titleB |
+----------+--------+
I already tried getting rid of 'foodType' in the SELECT clause, but if I do so, mysql tells me : "Unknown column 'food.type' in 'having clause'"
I already tried to GROUP BY 'recipeId' right before HAVING clause, but I get that error : "Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'myDb.food.type' which is not functionally dependent on columns in GROUP BY clause" (I understand that error).
I guess it has to do with something like "Grouping results after join and having clause", but I might be wrong...
Thanks a lot
Upvotes: 1
Views: 56
Reputation: 3032
just exclude all recipes which have at least one meat ingridient (i did it 10 years ago even without sql)
SELECT recipe.id, recipe.title FROM recipe
WHERE recipe.id NOT IN (
SELECT
recipe.id,
FROM recipe
INNER JOIN ingredient
on ingredient.recipe_id = recipe.id
INNER JOIN food
on food.id = ingredient.aliment_id
AND food.type IN ('meat', 'seafood', 'fish')
)
ORDER BY recipeId
Upvotes: 1
Reputation: 1173
GROUP BY
clause, so you shouldn't have a HAVING
clause. Use WHERE
insteadSELECT
SELECT DISTINT
instead of just SELECT
Also, you have another issue: The logic of your query isn't actually correct, even though it's returning apparently correct results with such a small set of sample data.
When looking at composition, you probably want to use EXISTS
and a subquery. Perhaps something like this (untested):
SELECT
recipe.id as recipeId,
recipe.title as title,
food.type as foodType
FROM recipe r
WHERE NOT EXISTS
(SELECT food.type
FROM ingredient INNER JOIN food on food.id = ingredient.aliment_id
WHERE ingredient.recipe_id = r.id AND
food.type IN ('meat', 'seafood','fish')
)
ORDER BY recipeId
Upvotes: 1