选择包含所有提到的值并排除多对多关系中的重复项的名称

Posted

技术标签:

【中文标题】选择包含所有提到的值并排除多对多关系中的重复项的名称【英文标题】:Select name that contains ALL mentioned values and excludes duplicates in many-to-many relationship 【发布时间】:2019-03-24 03:38:05 【问题描述】:

我对 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)
);

谢谢。

【问题讨论】:

这看起来像 SQL Server 代码,不是 mysql。另外,请阅读如何使用准备好的语句。您是否尝试过自己解决这个新查询? SQL question conjunction的可能重复 ntexttextimage 数据类型将在 SQL Server 的未来版本中删除。避免在新的开发工作中使用这些数据类型,并计划修改当前使用它们的应用程序。请改用nvarchar(max)varchar(max)varbinary(max)。 See details here 【参考方案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

【讨论】:

如果 number_of_ingredients 与该特定配方中的成分数量完全相同,则此查询有效,但是一旦添加了更多成分,则不会显示任何结果。如果选择了所有成分,则需要显示所有食谱,但目前不需要。 @goldenpeng 。 . .我明白你在说什么。您想计算匹配的成分。

以上是关于选择包含所有提到的值并排除多对多关系中的重复项的名称的主要内容,如果未能解决你的问题,请参考以下文章

排除具有多对多关系的行

多对多关系中的重复主键

多对多关系:使用数组或创建新表[重复]

JOINing多对多表时避免SQL查询中的重复行

过滤具有多对多关系的对象,检查它是不是包含列表中的至少一个元素

通过 SQLAlchemy 选择多个多对多关系