Выберите имя, которое содержит ВСЕ упомянутые значения и исключает дубликаты в отношениях «многие ко многим».

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

У меня есть SQL-запрос, который получает имена рецептов, содержащих ингредиенты, но мне нужно выбрать рецепты, которые содержат ВСЕ ингредиенты и исключают дубликаты.

" SELECT recipes.Name, recipes.Preperation_Time, recipes.Author FROM recipes" +
" INNER JOIN RecipeIngredients ON RecipeIngredients.Recipe_ID = recipes.Recipe_ID" +
" INNER JOIN Ingredients ON Ingredients.Ingredient_ID = RecipeIngredients.Ingredient_ID" +
" WHERE ingredients.Name IN (" + ingredientString + ")");

Вот мои таблицы, если это поможет:

CREATE TABLE [dbo].[recipes]
(
    [Recipe_ID]        INT IDENTITY (1, 1) NOT NULL,
    [Name]             VARCHAR(MAX) NOT NULL,
    [Instructions]     TEXT         NULL,
    [Preperation_Time] FLOAT(53)    NULL,
    [Author]           VARCHAR(MAX) NULL,

    CONSTRAINT [PK.recipes] 
        PRIMARY KEY CLUSTERED ([Recipe_ID] ASC)
 );

CREATE TABLE [dbo].[RecipeIngredients] 
(
    [Recipe_ID]     INT NOT NULL,
    [Ingredient_ID] INT NOT NULL,

    PRIMARY KEY CLUSTERED ([Recipe_ID] ASC, [Ingredient_ID] ASC),
    CONSTRAINT [FK_RecipeIngredients_To_Ingredients] 
        FOREIGN KEY ([Ingredient_ID]) 
        REFERENCES [dbo].[Ingredients] ([Ingredient_ID]),
    CONSTRAINT [FK_RecipeIngredients_To_Recipes] 
        FOREIGN KEY ([Recipe_ID]) 
        REFERENCES [dbo].[recipes] ([Recipe_ID])
 );

CREATE TABLE [dbo].[Ingredients] 
(
    [Ingredient_ID] INT IDENTITY (1, 1) NOT NULL,
    [Name]          VARCHAR(50) NOT NULL,

    PRIMARY KEY CLUSTERED ([Ingredient_ID] ASC)
);

Спасибо.


person goldenpeng    schedule 24.03.2019    source источник
comment
Это похоже на код SQL Server, не MySQL. Кроме того, пожалуйста, прочитайте о том, как использовать подготовленные операторы. Вы уже пытались решить этот новый запрос самостоятельно?   -  person Tim Biegeleisen    schedule 24.03.2019
comment
Возможный дубликат сочетания вопросов SQL   -  person Niayesh Isky    schedule 24.03.2019
comment
Типы данных ntext, text и image будут удалены в будущей версии SQL Server. Избегайте использования этих типов данных в новых разработках и планируйте модифицировать приложения, которые в настоящее время их используют. Вместо этого используйте nvarchar(max), varchar(max) и varbinary(max). Подробности см. здесь   -  person marc_s    schedule 24.03.2019


Ответы (1)


Вы можете использовать агрегацию. Я бы рекомендовал передавать ингредиенты в виде списка VALUES(), а не строк. Однако с вашей конструкцией:

SELECT r.Name, r.Preperation_Time, r.Author
FROM recipes r LEFT JOIN
     RecipeIngredients ri
     ON ri.Recipe_ID = r.Recipe_ID LEFT JOIN
     Ingredients i
     ON i.Ingredient_ID = ri.Ingredient_ID AND
        i.Name IN (" + ingredientString + ")"
GROUP BY r.Name, r.Preperation_Time, r.Author
HAVING COUNT(*) = COUNT(i.Ingredient_Id);  -- all match
person Gordon Linoff    schedule 24.03.2019
comment
Этот запрос работает, если number_of_ingredients точно совпадает с количеством ингредиентов в этом конкретном рецепте, но после добавления дополнительных ингредиентов результаты не отображаются. Если выбраны все ингредиенты, нужно показать все рецепты, но на данный момент этого не происходит. - person goldenpeng; 24.03.2019
comment
@goldenpeng . . . Я вижу, что вы говорите. Вы хотите посчитать совпадающие ингредиенты. - person Gordon Linoff; 24.03.2019