MySQL: запрос для получения рецептов с использованием всех заданных ингредиентов

0

У меня есть следующие упрощенные таблицы:

CREATE TABLE recipe(id int, name varchar(25));  
CREATE TABLE ingredient(name varchar(25));  
CREATE TABLE uses_ingredient(recipe_id int, name varchar(25));

Я хочу сделать запрос, который возвращает все id рецептов, содержащих как Chicken, так и Cream.

Я пробовал

SELECT recipe_id FROM uses_ingredient INNER JOIN  
(SELECT * FROM ingredient WHERE name="Chicken" OR name="Cream")  
USING (name) GROUP BY recipe_id  
HAVING COUNT(recipe_id) >= (SELECT COUNT(*) FROM theme);  

который дает мне: "ОШИБКА 1248 (42000): Каждая производная таблица должна иметь свой собственный псевдоним" и, вероятно, тоже ошибается.

Далее я попробовал

SELECT recipe_id FROM 
(SELECT * FROM ingredient WHERE name="Chicken" OR name="Cream") AS t 
INNER JOIN uses_ingredient USING (name) 
GROUP BY recipe_id HAVING 
COUNT(recipe_id)>= (SELECT COUNT(*) FROM t);

который дает "ERROR 1146 (42S02): Таблица" recipedb.t "не существует"

Я хочу избежать создания временных таблиц, включая использование ENGINE = MEMORY.

  • 0
    В вашем примере вы ссылаетесь на таблицу под названием THEME. Я понятия не имею, для чего это, поэтому я не упомянул об этом в своем ответе. Если это важно, пожалуйста, добавьте детали к своему вопросу.
  • 0
    Ошибка, которую вы увидели, имеет простое исправление: добавьте имя после производного запроса. SELECT recipe_id FROM ... JOIN (SELECT ...) name_it_here USING ...
Теги:
mysql-error-1248
mysql-error-1146

3 ответа

0

Другие предложения хороши, но вот другой способ. На самом деле это похоже на то, что вы пытались сделать в своем запросе. Хотя я не знаю, почему у вас есть таблица "ингредиент", когда одна и та же информация (имя), кажется, содержится в "use_ingredient".

SELECT recipe_id, count(*) c FROM uses_ingredient
WHERE name="Chicken" OR name="Cream"
GROUP BY recipe_id
HAVING c=2
  • 0
    Мне нравится твоя идея лучше. Но ни один из подходов не очень хорошо масштабируется. Например, если вы хотите, чтобы все рецепты с 4 конкретными ингредиентами, вы должны изменить количество. Кроме того, вам не нужно выбирать количество, достаточно иметь значение count (star) = 2 . Еще лучше, если вы скажете, где имя в ('a', 'b'), вы можете упростить еще больше. Вы можете посчитать количество элементов в этом массиве и сказать, где count (star) = @ nbr или что-то еще.
0

Я согласен с MJB; это пересечение двух множеств. Поэтому я бы просто получил два набора и посмотрел, что в них обоих...

SELECT *
    FROM recipe
    WHERE EXISTS (SELECT *
                      FROM uses_ingredient
                      WHERE uses_ingredient.recipe_id = recipe.recipe_id AND
                            uses_ingredient.name      = "Chicken") AND
          EXISTS (SELECT *
                      FROM uses_ingredient
                      WHERE uses_ingredient.recipe_id = recipe.recipe_id AND
                            uses_ingredient.name      = "Cream");
0

Вероятно, есть лучший способ подумать об этом, но я вижу ответ как пересечение двух наборов: те рецепты, в которых есть курица и те рецепты, в которых есть крем. Это может не сработать для вас, если вы упростите больше, чем просто количество столбцов. Но я попробовал это с горсткой записей, и это кажется прекрасным.

SELECT CH.Recipe_Id
FROM
  (SELECT Recipe_Id
  FROM Uses_Ingredient
  WHERE Name = 'Chicken') CH
INNER JOIN 
  (SELECT Recipe_Id
  FROM Uses_Ingredient
  WHERE Name = 'Cream') CR
  ON CR.Recipe_Id = CH.Recipe_Id

Ещё вопросы

Сообщество Overcoder
Наверх
Меню