I am doing an advanced search functionality for a recipes website where the users can query;
The above-mentioned points can be combined together in the user query.
I'm already half way through where I can query the recipes that include specified ingredients and cooked under certain amount of time.
Here's my database structure;
Table: Recipes
Recipe_ID, Recipe_Name, Cooking_time
Table: Ingredients
Ingredient_ID, Ingredient_Name
Table: Recipe_Ingredients
Recipe_Ingredient_ID, Ingredient_ID, Recipe_ID
Here's my SQL query so far;
SELECT count(*) as rowcount, r.Recipe_name
FROM Recipes AS r
INNER JOIN Recipe_Ingredients AS ri
ON r.Recipe_ID = ri.Recipe_ID
INNER JOIN Ingredients AS i
ON ri.Ingredient_ID = i.Ingredient_ID
AND i.Ingredient_Name IN ('penne','onion')
AND r.Cooking_time < 60
GROUP BY r.Recipe_name HAVING rowcount = 2;
The will get recipes that contain 'penne' and 'onion' and cooked in less than 60 minutes.
What I can't figure out is how to query recipes as per below;
I have tried the below code but it does not work;
SELECT count(*) as rowcount, r.Recipe_name
FROM Recipes AS r
INNER JOIN Recipe_Ingredients AS ri
ON r.Recipe_ID = ri.Recipe_ID
INNER JOIN Ingredients AS i
ON ri.Ingredient_ID = i.Ingredient_ID
AND i.Ingredient_Name IN ('penne','onion')
AND i.Ingredient_Name NOT IN ('butter')
AND r.Cooking_time < 60
GROUP BY r.Recipe_name HAVING rowcount = 2;
Any help is much appreciated!
Thanks.
You can use
SELECT r.Recipe_name,
r.Recipe_ID
FROM Recipes AS r
INNER JOIN Recipe_Ingredients AS ri
ON r.Recipe_ID = ri.Recipe_ID
INNER JOIN Ingredients AS i
ON ri.Ingredient_ID = i.Ingredient_ID
WHERE i.Ingredient_Name IN ( 'penne', 'onion', 'butter' )
AND r.Cooking_time < 60
GROUP BY r.Recipe_ID, /*<-- In case two recipes with same name*/
r.Recipe_name
HAVING
/*Must contain both these*/
COUNT(DISTINCT CASE
WHEN i.Ingredient_Name IN ( 'penne', 'onion' ) THEN i.Ingredient_Name
END) = 2
AND
/*Can't contain these*/
MAX(CASE
WHEN i.Ingredient_Name IN ( 'butter' ) THEN 1
ELSE 0
END) = 0