问题
Let's pretend I have a large recipe-database. A table for recipes each with an unique ID and a table for ingredients with a whole lot of sets like this:
ID | RECIPE | INGREDIENT
-------------------------------
1 | recipe_a | ingredient_a
2 | recipe_a | ingredient_b
3 | recipe_a | ingredient_c
4 | recipe_b | ingredient_a
5 | recipe_b | ingredient_d
6 | recipe_b | ingredient_e
Users can search for ingredients they want to see in their recipes and those they don't. The wanted query should be able to result in recipe_a when a user searches for recipes with ingredient_a and ingredient_b but not ingredient_d.
How would one do that in preferrably one query?
I tried the rather naive version with:
SELECT distinct recipe
from ingredients
where ingredient in (ingredient_a, ingredient_b)
and ingredient not in (ingredient_d)
This obv failed, because it still resulted in recipe_a and recipe_b, which it should do, because the rows 1 and 2 matched recipe_a and row 4 matched recipe_b.
回答1:
Select Distinct ...
From Recipes As R
Where R.ingredient in(ingredient_a, ingredient_b...)
And Not Exists(
Select 1
From Recipes As R2
Where R2.Recipe = R.Recipe
And R2.Ingredient In(ingredient_d)
)
As Jeffrey L Whitledge mentioned, the above query will return any recipe that has at least one ingredient in the desired list and none in the undesired list. However, if you wanted to return recipes that contained all the ingredients in the desired list and none in the undesired list you could do:
Select Distinct ...
From Recipes As R
Where Exists (
Select 1
From Recipes As R2
Where R2.Recipe = R.Recipe
And R2.ingredient in(ingredient_a, ingredient_b...)
Having Count(*) = @CountOfPassedIngredients
)
And Not Exists(
Select 1
From Recipes As R2
Where R2.Recipe = R.Recipe
And R2.Ingredient In(ingredient_d)
)
In this scenario, you would need to have first determine the count of desired ingredients.
来源:https://stackoverflow.com/questions/2420915/sql-query-needed-to-find-distinct-ids-probably-using-in-and-not-in