双连接上的结果太多

时间:2014-03-22 08:33:08

标签: mysql sql database-relations

我有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"

这是一个很好的衡量标准,显示一行,但标签和成分栏中的结果太多

http://sqlfiddle.com/#!2/626760/2

2 个答案:

答案 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 ', ')

检查小提琴:http://sqlfiddle.com/#!2/626760/4

答案 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