2012-08-16 3 views
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はhereです。

私が探しているチキンサラダパンケーキを返しますクエリです。 Aligator Burgersは、aligatorを使用しているため返されません。

私はサブ選択とALLキーワードを含むいくつかのことを試しましたが、運がなかった。私は様々な内側と外側の結合を試みましたが、少なくとも1つの成分が普及している限り、レシピの行はまだ表示されます。どんな助けでも大歓迎です!

私はPostgres 9.1を使用しています。

+1

を更新しましたこのモデルの質問です。私は新しいポスターを使ってそれを正しく行う方法を示しています。 –

答えて

7

これは、PopularIngredientsテーブルにない成分を持たないすべてのレシピを取得します。使用される成分のいずれもPopularIngredientsから失われていないことを確認するためにWHERE NOT EXISTSを使用し

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 
) 
+0

ありがとう!私はそれがどこかに '存在しない'存在することを知っていましたが、脳は最適な条件で働いていませんでした。 –

5

ビュー:

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
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) 
+1

私はこのアプローチが好きです。しかし、having句は、成分が複数回含まれるレシピを考慮するために、おそらくcount()よりもcount(distinct)でなければなりません。 –

+0

ありがとう!このアプローチは '+ 1'にも値する。 –

+0

@ GordonLinoff - ???私はDISTINCTを追加することで、結果を少し変えることができるかどうかは分かりません。レシピに成分が2回現れる場合、外部結合は2回成功するか、2回失敗します。それはDISTINCTなしでも正しい結果を得られます。 – dbenham

関連する問題