You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写SQL查询语句筛选出包含指定全部食材的菜品

需求说明

编写SQL查询返回至少包含指定全部食材的菜品,当前已有的查询仅能返回至少含列表中一种食材的结果,需要正确实现方案。

涉及表结构
Ingredients
============
ID
IngredientName
IngredientAmount
P_ID


Dishes
==========
ID
DishName


DishIngredients
==========
ID
DishID
IngredientID
初始错误版本查询

(仅能返回匹配任意一种食材的菜品)

DECLARE @IdIngredients nvarchar(1024) = '4174, 4028'
DECLARE @Ingredients TABLE (IdIngredient int) 
INSERT @Ingredients (IdIngredient)
SELECT Convert(int, value) FROM STRING_SPLIT(@IdIngredients, ',') 

SELECT DISTINCT D.Id
FROM Dishes D
INNER JOIN DishIngredients DI ON DI.DishID = D.ID
WHERE IngredientID IN (SELECT IdIngredient FROM @Ingredients)
待验证修改方案
DECLARE @IdIngredients nvarchar(1024) = '4174, 4028'
DECLARE @Ingredients TABLE (IdIngredient int) 
INSERT @Ingredients (IdIngredient)
SELECT Convert(int, value) FROM STRING_SPLIT(@IdIngredients, ',') 

SELECT DISTINCT D.Id
FROM Dishes D
INNER JOIN DishIngredients DI ON DI.DishID = D.ID
WHERE IngredientID IN (SELECT IdIngredient FROM @Ingredients)
GROUP BY D.Id
HAVING COUNT(D.Id) = (SELECT COUNT(*) FROM @Ingredients)
方案验证与优化
  • 你给出的修改方案是可行的,只要满足DishIngredients表中不存在同一个菜品重复关联同一个食材ID的情况(绝大多数业务中菜品食材关联表都会加DishID + IngredientID唯一约束,符合这个前提)
  • 可以去掉冗余的DISTINCT关键字,因为GROUP BY D.Id已经保证返回的菜品ID是唯一的,额外加DISTINCT会增加不必要的性能开销。
  • 如果需要同时返回菜品名称等其他字段,直接在SELECT和GROUP BY子句中添加对应字段即可。

优化后代码

DECLARE @IdIngredients nvarchar(1024) = '4174, 4028'
DECLARE @Ingredients TABLE (IdIngredient int) 
INSERT @Ingredients (IdIngredient)
SELECT Convert(int, value) FROM STRING_SPLIT(@IdIngredients, ',') 

SELECT D.Id, D.DishName
FROM Dishes D
INNER JOIN DishIngredients DI ON DI.DishID = D.ID
WHERE DI.IngredientID IN (SELECT IdIngredient FROM @Ingredients)
GROUP BY D.Id, D.DishName
HAVING COUNT(DISTINCT DI.IngredientID) = (SELECT COUNT(*) FROM @Ingredients)

额外补充:如果你的关联表确实存在同菜品同食材重复录入的情况,把COUNT里换成COUNT(DISTINCT DI.IngredientID)就可以规避这个问题

其他可选实现(双重NOT EXISTS写法)

如果你不想用分组计数的方式,也可以用如下写法,逻辑上是判断不存在任何一个指定食材是当前菜品没有的:

DECLARE @IdIngredients nvarchar(1024) = '4174, 4028'
DECLARE @Ingredients TABLE (IdIngredient int) 
INSERT @Ingredients (IdIngredient)
SELECT Convert(int, value) FROM STRING_SPLIT(@IdIngredients, ',') 

SELECT D.Id, D.DishName
FROM Dishes D
WHERE NOT EXISTS (
    SELECT 1 FROM @Ingredients I
    WHERE NOT EXISTS (
        SELECT 1 FROM DishIngredients DI 
        WHERE DI.DishID = D.ID AND DI.IngredientID = I.IdIngredient
    )
)

内容的提问来源于stack exchange,提问作者Gilles F

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 09:36:07