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

多Recipe场景下SQL查询失效:如何筛选用户Pantry含全食材的菜谱

问题分析与解决方案

原SQL语句的核心问题是内层的recipe_ingredient表未与外层recipe表关联,导致查询逻辑变成了“检查所有菜谱的所有食材是否都在用户Pantry中”,而非“检查单个菜谱的所有食材是否都在用户Pantry中”。只要有任意一个菜谱存在用户没有的食材,所有菜谱都会被过滤掉,这就是多菜谱场景下失效的原因。

修正后的NOT EXISTS写法

需要在第二层WHERE中添加关联条件,让recipe_ingredient只针对当前外层的recipe进行检查:

// 改用预处理语句避免SQL注入风险
$stmt = $mysqli->prepare('
SELECT r.* 
FROM recipe r
WHERE NOT EXISTS (
    SELECT 1 
    FROM recipe_ingredient ri
    WHERE ri.recipe_id = r.id  -- 关键:关联当前遍历的菜谱
      AND NOT EXISTS (
          SELECT 1 
          FROM pantry p
          WHERE p.ingredient_id = ri.ingredient_id 
            AND p.iduser = ?
      )
)
');
$stmt->bind_param('i', $_COOKIE["idUser"]);
$stmt->execute();
$res = $stmt->get_result();

另一种直观写法:分组统计验证

通过统计菜谱的总食材数,以及用户Pantry中匹配的食材数,当两者相等时,说明该菜谱的所有食材都被用户拥有:

$stmt = $mysqli->prepare('
SELECT r.*
FROM recipe r
JOIN recipe_ingredient ri ON r.id = ri.recipe_id
LEFT JOIN pantry p ON ri.ingredient_id = p.ingredient_id AND p.iduser = ?
GROUP BY r.id
HAVING COUNT(ri.ingredient_id) = COUNT(p.ingredient_id)
');
$stmt->bind_param('i', $_COOKIE["idUser"]);
$stmt->execute();
$res = $stmt->get_result();

重要提醒

原代码直接拼接$_COOKIE["idUser"]到SQL语句中,存在严重的SQL注入风险,上面的示例都改用了预处理语句绑定参数,这是必须修正的安全问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:57:07