3

我有 3 个表(仅对​​此处的问题列很重要):

USERS              GROUPS                 USERS_GROUPS
id                 id                     user_id
                   importance             group_id
                   color                   

如您所见,一个用户可以在多个组中,每个组都有不同的颜色,有些组比其他组更重要。例如,用户 A 在组编辑器(蓝色)和版主(绿色)中。他应该以什么颜色可见?绿色,因为版主比编辑更重要。

但我不知道(也许在一个查询中不可能?)如何从表组中获取用户的颜色。我创建了这样的查询:

SELECT * FROM `users` INNER JOIN users_groups ON users_groups.user_id = users.id INNER JOIN groups ON groups.id=users_groups.group_id 

但它返回与用户组一样多的用户行,如下所示:

 USERNAME   (...)    GROUP_ID       NAME (group)         COLOR       IMPORTANCE
 user                2              moderator            green       50
 user                3              editor               blue        25
 administrator       1              admin                orange      100
 administrator       3              editor               blue        25

我只想获得最重要的组-管理员作为组管理员的成员,用户作为组版主的成员。

4

2 回答 2

1

这是mysql中一个相当普遍的问题,它有几种不同的解决方案,通常最快的是加入一个选择最高重要性的子查询来过滤结果。

SELECT users.*, groups.*
FROM `users` 
INNER JOIN users_groups 
ON users_groups.user_id = users.id 
INNER JOIN groups 
ON groups.id=users_groups.group_id
INNER JOIN (SELECT user_groups.user_id, MAX(importance) AS importance FROM groups GROUP BY user_id) mxGrp
ON (groups.user_id = mxGrp.user_id AND groups.importance = mxGrp.importance);

阅读此博客文章以讨论其他可能的解决方案。

于 2013-06-27T14:17:12.897 回答
1

选项 1: 此选项为每个用户获取最重要的组,然后返回groups表中查找该组的颜色。额外的 JOIN 是需要的,因为初始的 GROUP BY 不一定会获取与 MAX(importance) 结果对应的正确颜色。

SELECT T1.*, groups.color FROM
(
    SELECT users.id, MAX(groups.importance) AS most_important_group FROM `users` 
    INNER JOIN 
    users_groups 
    ON users_groups.user_id = users.id 
    INNER JOIN groups 
    ON groups.id=users_groups.group_id
    GROUP BY users.id
) AS T1
INNER JOIN
groups
ON T1.most_important_group=groups.importance
GROUP BY T1.id

选项 2: 此选项以一种方式对初始结果集进行排序,该方式应将每个用户的最高重要性组以及该行中的相应颜色置于顶部。在外部 GROUP BY 之后,您应该只看到包含您想要的信息的每个用户的一行。您可以自定义要从子查询返回的字段。我包含了尽可能多的内容,但是如果您不需要它们,您应该减少它们(更少的字段应该意味着更快的结果)。

SELECT * FROM
(
    SELECT users.*, users_groups.*, groups.importance, groups.color FROM `users` 
    INNER JOIN users_groups 
    ON users_groups.user_id = users.id 
    INNER JOIN groups 
    ON groups.id=users_groups.group_id
    ORDER BY users.id, groups.importance DESC
) AS T1
GROUP BY T1.id

这些的性能将根据您的表大小以及您的索引结构而有所不同。尝试它们并响应哪个更快。如果您需要更快的运行时间,请随时使用来自这些查询的一些 EXPLAIN 语句和有关表的 DESCRIBE 语句来响应。

于 2013-06-27T14:30:11.027 回答