我在让 select 语句正常工作时遇到了一些麻烦。
我有以下表格:
食谱 | recipe_ingredient | 储藏室 |
---|---|---|
食谱1 | 成分1 | 材料1 |
食谱1 | 成分2 | 配料2 |
食谱2 | 成分3 |
我想要一个 select 语句,当用户的储藏室有该食谱的所有成分时返回食谱。
if ($res = $mysqli->query('
SELECT *
FROM recipe
WHERE NOT EXISTS (
SELECT recipe_id
FROM recipe_ingredient
WHERE NOT EXISTS (
SELECT ingredient_id
FROM pantry
WHERE recipe_ingredient.ingredient_id = pantry.ingredient_id
AND iduser = ' . $_COOKIE["idUser"] . '
)
)
')) {
我的代码在数据库中只有一个食谱时有效,但当添加多个食谱时,代码不再有效。以上表为例,它应该返回 recipe1 但它什么也不返回,除非食品储藏室有 ingredient3 然后返回两个食谱。
如何修改我的选择语句来解决这个问题?
你想要你的用户拥有所有成分的食谱,这看起来像一个关系除法问题。
从原始查询的表名和列名开始,这是一个为您提供食谱 ID 的查询:
select ri.recipe_id
from recipe_ingredient ri
inner join pantry p on p.ingredient_id = ri.ingredient_id
where p.iduser = ?
group by ri.recipe_id
having count(*) = (
select count(*)
from recipe_ingredient ri1
where ri1.recipe_id = r.recipe_id
)
想法是过滤用户拥有的配料的配方配料表,然后使用
having
子句确保没有遗漏相同的配方。
旁注:不要在查询中将参数连接为字符串,因为它会打开您的应用程序以进行 SQL 注入;改用绑定参数。
您可以使用 exists 执行以下相关子查询,这将测试所有成分是否已填满,这将是当所有 recipe_ingredient ingridents_id 的值不为 NULL
但是您应该知道您的代码容易受到 sql 注入 的影响,因此您应该只使用带参数的准备好的语句,请参阅如何防止 PHP 中的 SQL 注入? 以获取更多信息
SELECT * from recipe r
WHERE NOT EXISTS (SELECT
1
FROM recipe_ingredient rp LEFT JOIN pantry ON rp.ingredient_id
= p.ingredient_id
AND p.iduser= ?
WHERE rp.recipe_id = r.recipe_id AND p.ingredient_id IS NULL)