Search code examples
sqljoinwhere-clauserelational-division

SQL query through an intermediate table


Given the following tables:

Recipes
| id | name
| 1  | 'chocolate cream pie'
| 2  | 'banana cream pie'
| 3  | 'chocolate banana surprise'

Ingredients
| id | name
| 1  | 'banana'
| 2  | 'cream'
| 3  | 'chocolate'

RecipeIngredients
| recipe_id | ingredient_id
|     1     |      2
|     1     |      3
|     2     |      1
|     2     |      2
|     3     |      1
|     3     |      3

How do I construct a SQL query to find recipes where ingredients.name = 'chocolate' and ingredients.name = 'cream'?


Solution

  • This is called relational division. A variety of techniques are discussed here.

    One alternative not yet given is the double NOT EXISTS

    SELECT r.id, r.name
    FROM Recipes r
    WHERE NOT EXISTS (SELECT * FROM Ingredients i
                      WHERE name IN ('chocolate', 'cream')
                      AND NOT EXISTS
                          (SELECT * FROM RecipeIngredients ri
                           WHERE ri.recipe_id = r.id
                           AND ri.ingredient_id = i.id))