sql >> Base de Datos >  >> RDS >> Mysql

consulta mysql para seleccionar todo excepto algo

Considere este ejemplo...

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

Lo siguiente devuelve una lista de todas las recetas y los ingredientes necesarios para construirlas...

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

Ahora supongamos que tenemos una despensa que contiene queso, frijoles y tostadas. ¿Qué podemos construir usando SOLO esos ingredientes?

 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

Esto se puede reescribir así...

 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(*);