我有一个包含三个表的数据库:recipes
,ingredients
和allergens
。 recipes
和ingredients
以及ingredients
和allergens
之间存在多对多关系。这些关系使用中间表ingredient_in_recipe
和allergen_in_ingredient
来解决,这些中间表仅包含配方,成分和过敏原的相应ID。
现在,选择一组食谱中的所有食材很简单,例如id = 1,2,3,4和5的食谱就像这样:
SELECT i.* FROM ingredients AS i
INNER JOIN ingredient_in_recipe AS ir ON i.id = ir.ingredient_id
INNER JOIN recipes AS r ON ir.recipe_id = r.id
WHERE r.id IN (1, 2, 3, 4, 5);
此外,很容易添加更多INNER JOIN
和WHERE
子句以从结果数据集中删除某些成分。然而,当食谱中含有某种过敏原的成分时,我想从结果中删除所有匹配的成分,因为该过敏原中含有该过敏原的食谱,因为该食谱因过敏而不再有效。实现这一目标的最佳方法是什么?
答案 0 :(得分:1)
以下查询获得" safe"没有过敏原的食谱:
SELECT ir.recipe_id
FROM ingredient_in_recipe ir LEFT JOIN
allergens_in_ingredient ai
ON ai.ingredient_id = i.id
WHERE ir.recipe_id IN (1, 2, 3, 4, 5)
GROUP BY ir.recipe_id
HAVING MAX(ai.allergen_id IS NULL) IS NULL;
请注意,您不需要recipes
表或ingredients
表来获取" safe"配方
然后,您可以将其与成分一起加入,以便与他们的不满者一起获得安全食谱:
SELECT i.*
FROM (SELECT ir.recipe_id
FROM ingredient_in_recipe ir LEFT JOIN
allergens_in_ingredient ai
ON ai.ingredient_id = i.id
WHERE ir.recipe_id IN (1, 2, 3, 4, 5)
GROUP BY ir.recipe_id
HAVING MAX(ai.allergen_id IS NULL) IS NULL
) rsafe JOIN
ingredient_in_recipe ir
ON rsafe.recipe_id = ir.recipe_id JOIN
ingredients i INNER JOIN
ON i.id = ir.ingredient_id
ORDER BY i.recipe_id;
答案 1 :(得分:0)
这是我最终解决的问题。我没有在问题中明确说明,但是最好从列表中删除任何含有过敏原成分的配方。在下面,它在所有食谱和任何包含id为1,2或4的过敏原的配方中进行搜索。因为我不需要来自recipe
表的任何数据,所以它被排除在最后一部分之外。查询。
SELECT i.*, ir.*
FROM(SELECT ir.recipe_id
FROM ingredient_in_recipe AS ir LEFT JOIN
allergen_in_ingredient AS ai ON ai.ingredient_id = ir.ingredient_id
GROUP BY ir.recipe_id
HAVING NOT MAX(ai.allergen_id IN (1, 2, 14))
) AS rsafe LEFT JOIN
ingredient_in_recipe AS ir ON rsafe.recipe_id = ir.recipe_id INNER JOIN
ingredients AS i on i.id = ir.ingredient_id
ORDER BY i.id;