多个多对多关系连接上的 GROUP_CONCAT 产生重复项
GROUP CONCAT on multiple many-to-many relationsship joins produces duplicates
所以我有一个包含很多多对多关系的数据库。我有我的主要 items
table、一个 class
table 和一个 class_role
table。一个项目可以有多个 classes 和 class 角色。我想要的结果是这样的:
[{
ItemId: ...,
Name: ...,
Classes: 'Class1, Class2, Class3',
ClassRoles: 'ClassRole1, ClassRole2'
}...]
我目前的方法是像这样使用关系 tables:r_items_classes (Itemid, ClassId), r_items_class_roles (Itemid, ClassRoleId)
然后使用 GROUP_CONCAT 和 GROUP_BY 的查询像这样 (Class
和 ClassRole
只是相应 table 中的相应“名称”字段:
SELECT items.ItemId, items.Name, GROUP_CONCAT(Class) as Classes FROM items
JOIN r_items_classes ON items.ItemId = r_items_classes.ItemId
JOIN classes ON r_items_classes.ClassId = classes.ClassId
GROUP BY items.Itemid, items.Name
现在这非常适合多对多关系之一。但是,一旦我添加另一个这样的示例:
SELECT items.ItemId, items.Name, GROUP_CONCAT(Class) as Classes, GROUP_CONCAT(ClassRole) as ClassRoles FROM items
JOIN r_items_classes ON items.ItemId = r_items_classes.ItemId
JOIN classes ON r_items_classes.ClassId = classes.ClassId
JOIN r_items_class_roles ON items.ItemId = r_items_class_roles.ItemId
JOIN class_roles ON r_items_class_roles.ClassRoleId = class_roles.ClassRoleId
GROUP BY items.Itemid, items.Name
我在组连接中得到重复的结果,例如 Classes: 'Class1, Class1, Class2'
或 ClassRoles: 'ClassRole1, ClassRole1, ClassRole1'
。这是什么原因,我该如何解决?
最简单的解决方案是DISTINCT
:
SELECT items.ItemId, items.Name, GROUP_CONCAT(DISTINCT Class) as Classes,
GROUP_CONCAT(DISTINCT ClassRole) as ClassRoles
但是,通过预聚合或使用子查询分别进行每个串联可以提高性能。
所以,这可能更有效:
select i.*,
(select group_concat(c.class)
from r_items_classes ic join
classes c
on ic.ClassId = c.ClassId
where i.ItemId = ic.ItemId
) as classes,
(select group_concat(cr.ClassRole)
from r_items_class_roles icr join
class_roles cr
on icr.ClassId = cr.ClassId
where i.ItemId = icr.ItemId
) as ClassRoles
from items i;
这将有更好的性能,尤其是当基础表的索引设置正确时。
所以我有一个包含很多多对多关系的数据库。我有我的主要 items
table、一个 class
table 和一个 class_role
table。一个项目可以有多个 classes 和 class 角色。我想要的结果是这样的:
[{
ItemId: ...,
Name: ...,
Classes: 'Class1, Class2, Class3',
ClassRoles: 'ClassRole1, ClassRole2'
}...]
我目前的方法是像这样使用关系 tables:r_items_classes (Itemid, ClassId), r_items_class_roles (Itemid, ClassRoleId)
然后使用 GROUP_CONCAT 和 GROUP_BY 的查询像这样 (Class
和 ClassRole
只是相应 table 中的相应“名称”字段:
SELECT items.ItemId, items.Name, GROUP_CONCAT(Class) as Classes FROM items
JOIN r_items_classes ON items.ItemId = r_items_classes.ItemId
JOIN classes ON r_items_classes.ClassId = classes.ClassId
GROUP BY items.Itemid, items.Name
现在这非常适合多对多关系之一。但是,一旦我添加另一个这样的示例:
SELECT items.ItemId, items.Name, GROUP_CONCAT(Class) as Classes, GROUP_CONCAT(ClassRole) as ClassRoles FROM items
JOIN r_items_classes ON items.ItemId = r_items_classes.ItemId
JOIN classes ON r_items_classes.ClassId = classes.ClassId
JOIN r_items_class_roles ON items.ItemId = r_items_class_roles.ItemId
JOIN class_roles ON r_items_class_roles.ClassRoleId = class_roles.ClassRoleId
GROUP BY items.Itemid, items.Name
我在组连接中得到重复的结果,例如 Classes: 'Class1, Class1, Class2'
或 ClassRoles: 'ClassRole1, ClassRole1, ClassRole1'
。这是什么原因,我该如何解决?
最简单的解决方案是DISTINCT
:
SELECT items.ItemId, items.Name, GROUP_CONCAT(DISTINCT Class) as Classes,
GROUP_CONCAT(DISTINCT ClassRole) as ClassRoles
但是,通过预聚合或使用子查询分别进行每个串联可以提高性能。
所以,这可能更有效:
select i.*,
(select group_concat(c.class)
from r_items_classes ic join
classes c
on ic.ClassId = c.ClassId
where i.ItemId = ic.ItemId
) as classes,
(select group_concat(cr.ClassRole)
from r_items_class_roles icr join
class_roles cr
on icr.ClassId = cr.ClassId
where i.ItemId = icr.ItemId
) as ClassRoles
from items i;
这将有更好的性能,尤其是当基础表的索引设置正确时。