我有一个让我难过的SQL查询。基本上,我有一个Recipes
表,其中包含(正如您无疑猜测的那样)许多食谱。我有一个Ingredients
表,其中包含各种成分。我有一个RecipeIngredients
表,它将食谱与其使用的成分联系起来。最后,我有一张PopularIngredients
表(它实际上是一个视图,但是谁在乎?),其中包含了人们在厨房中最常用的成分:
CREATE Table Recipes
(
RecipeId int4,
Title varchar(100)
);
CREATE Table Ingredients
(
IngredientId int4,
Name varchar(100)
);
CREATE Table RecipeIngredients
(
RecipeId int4,
IngredientId int4,
Amount int2
);
CREATE Table PopularIngredients
(
IngredientId int4
);
我的目标是获取所有使用 热门成分的食谱清单。
可以找到带有示例数据的SQL小提琴here。
我正在寻找的是一个将返回 Chicken Salad 和 Pancakes 的查询。 Aligator Burgers 不会被退回,因为它使用的 aligator 不是一种受欢迎的成分。
我尝试了一些涉及子选择和ALL
关键字的事情,但没有运气。我已经尝试了各种内部和外部连接,但只要至少有一种成分很受欢迎,配方行仍然会出现。任何帮助将不胜感激!
我使用的是Postgres 9.1。
答案 0 :(得分:7)
这将获得所有不含在PopularIngredients表中的成分的食谱。
select * from Recipes r where not exists (
select * from RecipeIngredients ri
left join PopularIngredients pi on pi.IngredientId=ri.IngredientId
where ri.RecipeId=r.RecipeId and pi.IngredientId is null
)
答案 1 :(得分:5)
使用WHERE NOT EXISTS
确保PopularIngredients视图中没有遗漏任何成分:
SELECT R.*
FROM Recipes R
WHERE NOT EXISTS (
SELECT 1
FROM RecipeIngredients RI
LEFT JOIN PopularIngredients P ON P.IngredientId = RI.IngredientId
WHERE RI.RecipeId = R.RecipeId AND P.IngredientId IS NULL
)
更新了您的SqlFiddle
答案 2 :(得分:2)
select r.Title
from Recipes r
join RecipeIngredients ri
on r.RecipeId = ri.RecipeId
left outer join PopularIngredients pi
on ri.IngredientId = pi.IngredientId
group by r.Title
having count( case when pi.IngredientId is null then 1 end )=0
或几乎相同
select r.Title
from Recipes r
join RecipeIngredients ri
on r.RecipeId = ri.RecipeId
left outer join PopularIngredients pi
on ri.IngredientId = pi.IngredientId
group by r.Title
having count(pi.IngredientId)=count(ri.IngredientId)