Reputation: 220
With the tables
CREATE TABLE recipeingredients(recipeid int, ingredientid int);
CREATE TABLE ingredients(ingredientid int primary key, name text, perishable int);
ingredients
1 'ingA' 0
2 'ingB' 1
3 'ingC' 1
4 'ingD' 0
recipeingredients
1 1
1 2
2 1
2 2
2 3
3 2
3 4
The recipeingredients table is for storing all the ingredients a recipe may have, and ingredients is for storing the qualities of each unique ingredient.
I was joining recipeingredients to ingredients via the query:
SELECT * FROM recipeingredients
INNER JOIN (SELECT ingredientid, name, perishable FROM ingredients) i
ON recipeingredients.ingredientid = i.ingredientid
because the 'perishable' data.
Now if I want to exclude all recipes that have one of a given, static list of ingredient IDs from the selection, how would I go about doing that?
I tried the intuitive selection
SELECT * FROM recipeingredients
INNER JOIN (SELECT ingredientid, name, perishable FROM ingredients
WHERE ingredientid NOT IN (1, 3)
) i
ON recipeingredients.ingredientid = i.ingredientid
which does not work, obviously.
That is, this is the sort of selection I want to be returned, assuming the forbidden ingredient ids are 1 and 3:
recipeid|ingredientid| name |perishable
3 2 'ingB' 1
3 4 'ingD' 0
since recipes 1 and 2 both have either 1 or 3 in them.
How would I go about making this selection work? Would I need a new table of ingredients to recipe IDs to filter against?
Upvotes: 1
Views: 44
Reputation: 180020
You do not need to use a subquery to do a join, and joins can be simplified with a USING clause if both column names match:
SELECT recipeid,
ingredientid,
name,
perishable
FROM recipeingredients
JOIN ingredients USING (ingredientid);
Anyway, the WHERE clause on the SELECT ... FROM ingredients
subquery returns all ingredients not on your list.
If you want to exclude all recipes that have one of a given, static list of ingredient IDs, you have to write that in SQL.
This query would select all recipe IDs that have one of a given, static list of ingredient IDs:
SELECT DISTINCT recipeid
FROM recipeingredients
WHERE ingredientid IN (1, 3);
And this query then excludes those recipes from the result:
SELECT recipeid,
ingredientid,
name,
perishable
FROM recipeingredients
JOIN ingredients USING (ingredientid)
WHERE recipeid NOT IN (SELECT recipeid
FROM recipeingredients
WHERE ingredientid IN (1, 3));
Upvotes: 1