この例を考えてみましょう...
SELECT * FROM recipes;
+-----------+---------------------------------+
| recipe_id | recipe |
+-----------+---------------------------------+
| 6 | Beans & Macaroni |
| 9 | Beans on Jacket Potato |
| 3 | Beans on Toast |
| 10 | Cheese & Beans on Jacket Potato |
| 4 | Cheese & Beans on Toast |
| 2 | Cheese on Toast |
| 1 | Macaroni & Cheese |
| 12 | Peanut Butter on Toast |
| 5 | Toast & Jam |
+-----------+---------------------------------+
SELECT * FROM recipe_ingredient;
+-----------+---------------+
| recipe_id | ingredient_id |
+-----------+---------------+
| 1 | 1 |
| 1 | 2 |
| 2 | 2 |
| 2 | 4 |
| 3 | 3 |
| 3 | 4 |
| 4 | 2 |
| 4 | 3 |
| 4 | 4 |
| 5 | 4 |
| 5 | 5 |
| 6 | 1 |
| 6 | 3 |
| 9 | 3 |
| 9 | 6 |
| 10 | 2 |
| 10 | 3 |
| 10 | 6 |
| 12 | 4 |
| 12 | 7 |
+-----------+---------------+
SELECT * FROM ingredients;
+---------------+---------------+
| ingredient_id | ingredient |
+---------------+---------------+
| 3 | Beans |
| 2 | Cheese |
| 6 | Jacket Potato |
| 5 | Jam |
| 1 | Macaroni |
| 7 | Peanut Butter |
| 4 | Toast |
+---------------+---------------+
以下は、すべてのレシピとそれらを構築するために必要な材料のリストを返します...
SELECT r.*
, i.*
FROM recipes r
JOIN recipe_ingredient ri
ON ri.recipe_id = r.recipe_id
JOIN ingredients i
ON i.ingredient_id = ri.ingredient_id;
+-----------+---------------------------------+---------------+---------------+
| recipe_id | recipe | ingredient_id | ingredient |
+-----------+---------------------------------+---------------+---------------+
| 6 | Beans & Macaroni | 1 | Macaroni |
| 6 | Beans & Macaroni | 3 | Beans |
| 9 | Beans on Jacket Potato | 3 | Beans |
| 9 | Beans on Jacket Potato | 6 | Jacket Potato |
| 3 | Beans on Toast | 3 | Beans |
| 3 | Beans on Toast | 4 | Toast |
| 10 | Cheese & Beans on Jacket Potato | 2 | Cheese |
| 10 | Cheese & Beans on Jacket Potato | 3 | Beans |
| 10 | Cheese & Beans on Jacket Potato | 6 | Jacket Potato |
| 4 | Cheese & Beans on Toast | 2 | Cheese |
| 4 | Cheese & Beans on Toast | 3 | Beans |
| 4 | Cheese & Beans on Toast | 4 | Toast |
| 2 | Cheese on Toast | 2 | Cheese |
| 2 | Cheese on Toast | 4 | Toast |
| 1 | Macaroni & Cheese | 1 | Macaroni |
| 1 | Macaroni & Cheese | 2 | Cheese |
| 12 | Peanut Butter on Toast | 4 | Toast |
| 12 | Peanut Butter on Toast | 7 | Peanut Butter |
| 5 | Toast & Jam | 4 | Toast |
| 5 | Toast & Jam | 5 | Jam |
+-----------+---------------------------------+---------------+---------------+
ここで、チーズ、ビーンズ、トーストが入ったパントリーがあるとします。それらの材料のみを使用して、何を構築できますか?
SELECT r.*
, SUM(CASE WHEN ingredient IN ('Cheese','Beans','Toast') THEN 1 ELSE 0 END) x
, COUNT(*) y
FROM recipes r
JOIN recipe_ingredient ri ON ri.recipe_id = r.recipe_id
JOIN ingredients i ON i.ingredient_id = ri.ingredient_id
GROUP
BY r.recipe_id;
+-----------+---------------------------------+------+---+
| recipe_id | recipe | x | y |
+-----------+---------------------------------+------+---+
| 1 | Macaroni & Cheese | 1 | 2 |
| 2 | Cheese on Toast | 2 | 2 | <--
| 3 | Beans on Toast | 2 | 2 | <--
| 4 | Cheese & Beans on Toast | 3 | 3 | <-- *
| 5 | Toast & Jam | 1 | 2 |
| 6 | Beans & Macaroni | 1 | 2 |
| 9 | Beans on Jacket Potato | 1 | 2 |
| 10 | Cheese & Beans on Jacket Potato | 2 | 3 |
| 12 | Peanut Butter on Toast | 1 | 2 |
+-----------+---------------------------------+------+---+
x = y : recipes use only those ingredients found in the pantry.
x = y = total no of ingredients in pantry : recipes using EXACTLY the ingredients found in the pantry
これは次のように書き換えることができます...
SELECT r.*
FROM recipes r
JOIN recipe_ingredient ri ON ri.recipe_id = r.recipe_id
JOIN ingredients i ON i.ingredient_id = ri.ingredient_id
GROUP
BY r.recipe_id
HAVING SUM(CASE WHEN ingredient IN ('Cheese','Beans','Toast') THEN 1 ELSE 0 END) = COUNT(*);