我有一个多对多关系,通过联结表连接。我的具体案例是食谱和配料。我想选择所有不包含未在给定列表中的成分的食谱。例如,如果我输入奶酪、 toast 和 cookies ,我希望结果包括 toast 上的奶酪、 cookies 上的奶酪,但不包括 toast 上的果酱。
所以类似:
SELECT * FROM
recipe
JOIN recipe_ingredient on recipe.id = recipe_ingredient.recipe_id
JOIN ingredient on ingredient.id = recipe_ingredient.ingredient_id
WHERE ingredient.name
???
("cheese", "toast", "crackers")
选择包含任何或所有这些成分的食谱很容易,但如果可以避免,我不想随后过滤掉包含未列出成分的结果。
编辑:
一些示例表:
ingredient
-----------
id | name
1 | "cheese"
2 | "toast"
3 | "crackers"
4 | "jam"
recipe
-----------
id | name
1 | "cheese on toast"
2 | "cheese with crackers"
3 | "jam on toast"
recipe_ingredient
-------------------------
recipe_id | ingredient_id
1 | 1
1 | 2
2 | 1
2 | 3
3 | 2
3 | 4
最佳答案
实现这一目标的一种方法是选择包含您的标准中未列出的任何成分的食谱,以使用 ALL
进行匹配。使用子查询:
SELECT r.id
FROM recipe r
JOIN recipe_ingredient ri on r.id = ri.recipe_id
JOIN ingredient i on i.id = ri.ingredient_id
WHERE i.name <> ALL ( SELECT 'cheese' UNION SELECT 'toast' UNION SELECT 'crackers' )
GROUP BY r.id
要仅检索与您的条件匹配的食谱,您可以使用相同的 <> ALL
包装上述语句。比较。
SELECT *
FROM recipe
WHERE id <> ALL (
SELECT r.id
FROM recipe r
JOIN recipe_ingredient ri on r.id = ri.recipe_id
JOIN ingredient i on i.id = ri.ingredient_id
WHERE i.name <> ALL ( SELECT 'cheese' UNION SELECT 'toast' UNION SELECT 'crackers' )
GROUP BY r.id
);
补充说明:实际上NOT IN
是 <> ALL
的别名,因此您可以互换使用它们。
给定您的示例,它只会返回:
id | name
---|-------------------------
1 | cheese on toast
2 | cheese with crackers
在这里查看它的工作情况:http://sqlfiddle.com/#!9/f20010/25
关于MySQL多对多联结表: Select all entries from A which contain no values in B not in list,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35675354/