8

我有一个让我难过的 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 Fiddle 。

我正在寻找的是一个将返回Chicken SaladPancakes的查询。 Aligator Burgers不会被退回,因为它使用了不受欢迎的成分。

我尝试了一些涉及子选择和ALL关键字的事情,但没有任何运气。我尝试了各种内部和外部联接,但只要其中至少一种成分很受欢迎,食谱行仍然会出现。任何帮助将非常感激!

我正在使用 Postgres 9.1。

4

3 回答 3

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
)
于 2012-08-16T00:52:30.753 回答
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

于 2012-08-16T00:53:50.290 回答
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)
于 2012-08-16T01:10:07.353 回答