从页面 - MyBarCabinet - 我可以选择我可用的原材料。这些原材料(仅ID)放入一个数组并存储在cookie中。
现在;我的目标是只获得不需要更多/其他原料的饮料,而不是存储在饼干中的饮料。换一种说法;如果我检查过我只有“16”,“34”和“35”可用:只有那些只需要这些原料的饮料才会出现,而不是其他原料中含有这些原料的饮料。
我从MySQL数据库查询饮料和所有这些。这部分由三个表组成:drinks_recipes
,drink_recipes_ingredients
和raw_materials
drink_recipes_ingredients
- 表用于将饮料配方与原料“链接”。
如果我这样做:
SELECT
dr.id drink_id, dr.name drink_name,
rm.name ingredient_name
FROM drink_recipes_ingredients dri
JOIN drink_recipes dr ON dr.id = dri.fk_recipes_id
JOIN raw_materials rm ON rm.id = dri.fk_raw_materials_id
WHERE rm.id IN (16,34,35)
这正是我不想要的。我得到的所有饮料中都含有至少一种选定的原料。
我确实看过这篇文章:How to return a row only if multiple clauses are met,但在我的案例中我无法弄清楚如何做类似的事情。但目标看起来是一样的。
答案 0 :(得分:2)
Baramar似乎有一个有趣的解决方案,但对于这种问题,我通常使用“找到相反的”方法。我们首先找到与您的清单不符的所有饮料。然后我们选择那些不是那些的饮料:
SELECT *
FROM drink_recipes
WHERE drink_recipes.id NOT IN (
SELECT
dr.id
FROM drink_recipes_ingredients dri
JOIN drink_recipes dr ON dr.id = dri.fk_recipes_id
JOIN raw_materials rm ON rm.id = dri.fk_raw_materials_id
WHERE rm.id NOT IN (16,34,35)
)
答案 1 :(得分:1)
不是返回与成分匹配的行,而是计算匹配的所选成分的数量。然后你可以将它与成分总数进行比较,看看是否还有其他成分。
SELECT
dr.id drink_id, dr.name drink_name,
rm.name ingredient_name,
SUM(rm.id IN (16, 34, 35)) AS matched_count,
COUNT(*) AS all_count
FROM drink_recipes_ingredients dri
JOIN drink_recipes dr ON dr.id = dri.fk_recipes_id
JOIN raw_materials rm ON rm.id = dri.fk_raw_materials_id
GROUP BY dr.id
HAVING matched_count > 0 AND matched_count = all_count
答案 2 :(得分:0)
我有其他解决方案......从数学的角度来看,也许并不那么优雅。
SELECT
dr.id drink_id
, dr.name drink_name
, rm.name ingredient_name
FROM
drink_recipes_ingredients dri
JOIN drink_recipes dr ON dr.id = dri.fk_recipes_id
JOIN raw_materials rm ON rm.id = dri.fk_raw_materials_id
GROUP BY dr.id, dr.name, rm.name
WHERE GROUP_CONCAT(rm.id ORDER BY rm.id SEPARATOR '|') = '16|34|35'
字符串'16|34|35'
是来自cookie的连接ID。您可以在应用程序代码中进行准备。