Как я могу найти все строки в таблице, которые имеют исключительно связанные строки в данном списке? - PullRequest
1 голос
/ 31 марта 2012

У меня есть три таблицы. Думайте о них как о следующем:

  Recipes
  id | name
  1  | Cookies
  2  | Soup
  ...


  Ingredients
  id | name
  1  | flour
  2  | butter
  3  | chicken
  ...

  Recipe_Ingredient
  recipe_id | ingredient_id
  1         | 1
  1         | 2
  2         | 3

Надеюсь, вы поняли идею. Мне нужен запрос, в котором я могу найти все рецепты, в которых есть ингредиенты, которые являются подмножеством данного набора ингредиентов.

Идея в том, что я хотел бы иметь список всего, что я могу сделать с тем, что у меня есть под рукой (но, конечно, не ВСЕ, что у меня есть под рукой.)

Я пытался реализовать это с различными уровнями подзапросов и коррелировать подзапросы с EXISTS, но безуспешно. Я также пытался использовать HAVING и COUNT, но мне кажется, что это работает, только если я хочу что-то, что использует ВСЕ ингредиенты, которые у меня под рукой.

Ответы [ 2 ]

1 голос
/ 01 апреля 2012

Проверьте это, если это работает. Предполагая, что у вас есть (уникальные) идентификаторы ингредиентов, доступные в таблице ингредиенты ингредиенты, этот запрос должен показать идентификатор рецепта, который содержит полные ингредиенты:

    SELECT recipe_id
    FROM [select recipe_id, count(*) as num_of_ingredients from recipe_ingredient group by recipe_id]. AS x, [select recipe_ingredient.recipe_id as recipe_id, count(*) as num_of_ingredients 
    from recipe_ingredient, ingredients_avail               
    where               
     recipe_ingredient.ingredient_id = ingredients_avail.ingredient_id
    group by recipe_ingredient.recipe_id]. AS y               
    WHERE x.recipe_id = y.recipe_id and               
    x.num_of_ingredients = y.num_of_ingredients;               

Кроме того, здесь используется более типичный синтаксис:

  SELECT x.recipe_id 
    FROM ( 
      SELECT recipe_id, count(*) as num_of_ingredients 
        FROM recipe_ingredients
      GROUP BY recipe_id
     ) x, ( 
      SELECT recipe_id, count(*) as num_of_ingredients 
        FROM recipe_ingredients
        JOIN ingredients_avail 
          ON recipe_ingredients.ingredient_id = ingredients_avail.ingredient_id 
      GROUP BY recipe_id
     ) y 
  WHERE x.recipe_id = y.recipe_id AND x.num_of_ingredients = y.num_of_ingredients;
1 голос
/ 31 марта 2012
    mysql>
    mysql> select * from ingredients;
    +------+---------------+-----------+
    | id   | name          | available |
    +------+---------------+-----------+
    |    1 | salt          | n         |
    |    2 | sugar         | n         |
    |    3 | flour         | n         |
    |    4 | butter        | n         |
    |    5 | vanilla       | n         |
    |    6 | baking powder | n         |
    |    7 | egg           | n         |
    +------+---------------+-----------+
    7 rows in set (0.00 sec)

    mysql> select * from recipes;
    +------+---------------+
    | id   | name          |
    +------+---------------+
    |    1 | cookie        |
    |    2 | soup          |
    |    3 | xtreme flavor |
    +------+---------------+
    3 rows in set (0.00 sec)

    mysql> select * from recipe_ingredient;
    +-----------+---------------+
    | recipe_id | ingredient_id |
    +-----------+---------------+
    |         1 |             1 |
    |         1 |             2 |
    |         1 |             3 |
    |         1 |             4 |
    |         1 |             5 |
    |         1 |             6 |
    |         1 |             7 |
    |         2 |             1 |
    |         2 |             7 |
    |         3 |             4 |
    |         3 |             3 |
    +-----------+---------------+
    11 rows in set (0.00 sec)

    mysql>
    mysql> update ingredients set available = 'n';
    Query OK, 0 rows affected (0.00 sec)
    Rows matched: 7  Changed: 0  Warnings: 0

    mysql>
    mysql> update ingredients set available = 'y'
        -> where id in  (1,2,3,4,5,6,7);
    Query OK, 7 rows affected (0.00 sec)
    Rows matched: 7  Changed: 7  Warnings: 0

    mysql>
    mysql> select recipes.name from
        -> (select recipe_id, available from
        -> recipe_ingredient,
        -> ingredients
        -> where ingredient_id = ingredients.id
        -> group by  recipe_id, available) x, recipes
        -> where recipes.id = x.recipe_id
        -> group by x.recipe_id
        -> having count(*) = 1
        -> and max(x.available) = 'y';
    +---------------+
    | name          |
    +---------------+
    | cookie        |
    | soup          |
    | xtreme flavor |
    +---------------+
    3 rows in set (0.06 sec)

    mysql>
    mysql> update ingredients set available = 'n';
    Query OK, 7 rows affected (0.00 sec)
    Rows matched: 7  Changed: 7  Warnings: 0

    mysql>
    mysql> update ingredients set available = 'y'
        -> where id in  (1,7);
    Query OK, 2 rows affected (0.00 sec)
    Rows matched: 2  Changed: 2  Warnings: 0

    mysql>
    mysql> select recipes.name from
        -> (select recipe_id, available from
        -> recipe_ingredient,
        -> ingredients
        -> where ingredient_id = ingredients.id
        -> group by  recipe_id, available) x, recipes
        -> where recipes.id = x.recipe_id
        -> group by x.recipe_id
        -> having count(*) = 1
        -> and max(x.available) = 'y';
    +------+
    | name |
    +------+
    | soup |
    +------+
    1 row in set (0.06 sec)

    mysql>
    mysql>
    mysql> update ingredients set available = 'n';
    Query OK, 2 rows affected (0.00 sec)
    Rows matched: 7  Changed: 2  Warnings: 0

    mysql>
    mysql> update ingredients set available = 'y'
        -> where id in  (4,3);
    Query OK, 2 rows affected (0.00 sec)
    Rows matched: 2  Changed: 2  Warnings: 0

    mysql>
    mysql> select recipes.name from
        -> (select recipe_id, available from
        -> recipe_ingredient,
        -> ingredients
        -> where ingredient_id = ingredients.id
        -> group by  recipe_id, available) x, recipes
        -> where recipes.id = x.recipe_id
        -> group by x.recipe_id
        -> having count(*) = 1
        -> and max(x.available) = 'y';
    +---------------+
    | name          |
    +---------------+
    | xtreme flavor |
    +---------------+
    1 row in set (0.05 sec)

    mysql>
    mysql>
    mysql> update ingredients set available = 'n';
    Query OK, 3 rows affected (0.00 sec)
    Rows matched: 7  Changed: 3  Warnings: 0

    mysql>
    mysql> update ingredients set available = 'y'
        -> where id in  (1,3,7);
    Query OK, 3 rows affected (0.00 sec)
    Rows matched: 3  Changed: 3  Warnings: 0

    mysql>
    mysql> select recipes.name from
        -> (select recipe_id, available from
        -> recipe_ingredient,
        -> ingredients
        -> where ingredient_id = ingredients.id
        -> group by  recipe_id, available) x, recipes
        -> where recipes.id = x.recipe_id
        -> group by x.recipe_id
        -> having count(*) = 1
        -> and max(x.available) = 'y';
    +------+
    | name |
    +------+
    | soup |
    +------+
    1 row in set (0.06 sec)
...