我的数据库中有3个表:食谱,配料和配方。配方和配料与多对多连接,因此表recipe_ingredients是一个连接表。我想从表食谱中选择所有食谱,其中不包含id为X的成分。它仍然会返回所有食谱。如果我写一个查询来返回配料X的配方,它就可以了。这是我的疑问:
select * from recipes
join recipe_ingredients ON recipes.id = recipe_ingredients.fk_Recipe
join ingredients ON recipe_ingredients.fk_Ingredient = ingredients.id
where recipe_ingredients.fk_Ingredient != 307
GROUP by recipes.url
答案 0 :(得分:1)
问题在于,如果配方中至少有一种成分不是307,那么您仍会包含配方,因为该成分将通过where
条件。
您可以使用having
条件,如下所示:
select recipes.url
from recipes
join recipe_ingredients on recipes.id = recipe_ingredients.fk_Recipe
join ingredients on ingredients.id = recipe_ingredients.fk_Ingredient
group by recipes.url
having not(sum(recipe_ingredients.fk_Ingredient = 307))
当与“积极”条件结合使用时,即必须使用某种成分时,请继续使用相同的模式,但这次没有not
:
select recipes.url
from recipes
join recipe_ingredients on recipes.id = recipe_ingredients.fk_Recipe
join ingredients on ingredients.id = recipe_ingredients.fk_Ingredient
group by recipes.url
having not(sum(recipe_ingredients.fk_Ingredient = 307))
and sum(recipe_ingredients.fk_Ingredient = 1105)
如果最重要的是你有成分数量的条件,那么在count
子句中添加having
条件,例如:
select recipes.url
from recipes
join recipe_ingredients on recipes.id = recipe_ingredients.fk_Recipe
join ingredients on ingredients.id = recipe_ingredients.fk_Ingredient
group by recipes.url
having not(sum(recipe_ingredients.fk_Ingredient = 307))
and sum(recipe_ingredients.fk_Ingredient = 1105)
and count(*) = 2
此方法应该非常高效:它不需要执行子查询或多次连接同一个表。
答案 1 :(得分:1)
作为307之外的成分的任何配方都将满足条件。
也就是说,对于这个查询,如果其中一个成分是307,则无关紧要,只要配方中除了307之外还有其他成分,它就是匹配。
要获得没有307作为成分的配方,我们可以使用反连接或非EXISTS
反连接模式
$content = '<p>
<img src="#" alt="" class="image-1">
<img src="#" alt="" class="image-96">
<img src="#" alt="" class="image-12231">
<img src="#" alt="" class="image-444312">
</p>';
preg_match_all("/class=\"image-([0-9]+)\"/is", $content, $matches);
$images = $matches[1];
-OR -
不存在模式
SELECT r.id
, r.url
FROM recipes r
LEFT
JOIN recipe_ingredients s
ON s.fk_recipe = r.id
AND s.fk_ingredient = 307
WHERE s.fk_ingredient IS NULL
关注
要返回不的食谱有307作为成分,但做有42作为成分......
SELECT r.id
, r.url
FROM recipes r
WHERE NOT EXISTS
( SELECT 1
FROM recipe_ingredients s
WHERE s.fk_recipe = r.id
AND s.fk_ingredient = 307
)
-OR -
SELECT r.id
, r.url
FROM recipes r
JOIN recipe_ingredients t
ON t.fk_recipie = r.id
AND t.fk_ingredient = 42
LEFT
JOIN recipe_ingredients s
ON s.fk_recipe = r.id
AND s.fk_ingredient = 307
WHERE s.fk_ingredient IS NULL