我有3个表需要从中获取数据:
RECIPE - id, name, worktime, date, describtion
TAGS - id, name
INGREDIENT - id, name, created
现在,标签和成分都与食谱有多对多的关系。
当我尝试查询我的数据库以生成结果时,我得到的结果太多了。
SELECT *
FROM (`recipe` r, `tag` t, `ingredient` i)
JOIN `recipe_has_tag` rt ON `rt`.`tag_t_id` = `t`.`t_id`
JOIN `ingredient_has_recipe` ir ON `ir`.`ingredient_in_id` = `i`.`in_id`
WHERE `r`.`r_id` = ir.recipe_r_id
AND r.r_id = rt.recipe_r_id
AND r.r_id = ir.recipe_r_id
AND r.r_id = 1
我这个特殊的例子,我希望得到1个食谱,4个标签和4个成分。
问题是,它不是返回4行,而是将成分与标签混合,返回16个结果而不是预期的4个。
现在我最终获得了16个结果,其中每个标签都有一个含有成分的行,结果是16个结果。
得到这样的东西(非常简化)
R.name = good dish, i.name = potato, t.name = "potato dish"
R.name = good dish, i.name = carrot, t.name = "potato dish"
R.name = good dish, i.name = potato, t.name = "carrot dish"
R.name = good dish, i.name = carrot, t.name = "carrot dish"
我想要的是每行包含1个标签和1个成分的行,如下所示
R.name = good dish, i.name = potato, t.name = "potato dish"
R.name = good dish, i.name = carrot, t.name = "carrot dish"
这是一个很好的衡量标准,显示一行,但标签和成分栏中的结果太多
答案 0 :(得分:1)
好吧,只要您尝试检索1个食谱,4个标签和4个成分,问题就是:您想要它吗?当你要去3个表时,每个表有4个和4个,逻辑上有16行:在每一行中,你将拥有一个来自你所寻找的属性。
其他问题是,如果你想将它们全部放在一个唯一的行中,那么你必须在一个字段中将所有这些组合在一起,如果你想同时检索所有这些:
我猜你有这样的索引表:
recipe_has_tag - recipe_r_id, tag_t_id
ingredients_has_recipe - recipe_r_id, ingredient_in_id
所以,我要做的就是在一行中检索所有内容,用标签和成分的名称连接所有字段,然后在PHP中将它们爆炸或直接显示,具体取决于你想要的内容:
SELECT r.*,
GROUP_CONCAT( t.name SEPARATOR ', ' ) , GROUP_CONCAT( i.name SEPARATOR ', ')
FROM recipe r
-- Get Tags from recipe
JOIN recipe_has_tag rht ON rht.recipe_r_id = r.id
JOIN tag t ON rht.tag_t_id = t.id
-- Get Ingredients from recipe
JOIN ingredient_has_recipe ihr ON ihr.recipe_r_id = r.id
JOIN ingredients i ON ihr.ingredient_in_id = i.id
WHERE r.id = 1
GROUP BY r.id
其他方式是根据您想要获得的内容进行不同的查询,但只要我不知道您要对数据做什么,我就不能提出任何其他建议。
考虑到,我猜测索引表和连接的名称,也许你必须修改文件以具有正确的名称
更新
根据您的评论,您可能在表格中有重复的值。最好的解决方案是检查所有值并制作一个规范化的表,但是如果你改变了,你可以做一个解决方法
-- Change:
GROUP_CONCAT( t.name SEPARATOR ', ' ) , GROUP_CONCAT( i.name SEPARATOR ', ')
-- by
GROUP_CONCAT( DISTINCT( t.name SEPARATOR ) ', ' ) , GROUP_CONCAT( DISTINCT( i.name ) SEPARATOR ', ')
答案 1 :(得分:1)
从你的SQL小提琴中我认为你不想选择四行,因为你一直在告诉我们,但只有一个记录。您正在使用group_concat并获取重复的字符串。您可以通过将group_concat与DISTINCT:
一起使用来避免这种情况SELECT r.*,
GROUP_CONCAT(DISTINCT t.t_name SEPARATOR ', ' ) , GROUP_CONCAT(DISTINCT i.in_name SEPARATOR ', ')
FROM recipe r
JOIN recipe_has_tag rht ON rht.recipe_r_id = r.r_id
JOIN tag t ON rht.tag_t_id = t.t_id
JOIN ingredient_has_recipe ihr ON ihr.recipe_r_id = r.r_id
JOIN ingredient i ON ihr.ingredient_in_id = i.in_id
WHERE r.r_id = 1
GROUP BY r.r_id;
以下是更正的SQL小提琴:http://sqlfiddle.com/#!2/626760/5。