选择具有最高显示优先级的多个用户组

时间:2012-05-05 16:00:21

标签: mysql sql

我试图让它选择具有最高显示优先级的组。 问题是它选择ID最低的组,我不知道如何选择具有最高显示优先级的组。

SQL查询如下所示:

SELECT xf_user_group_relation.user_id , 
       xf_user_field_value.field_value,
       xf_user_group_relation.user_group_id, 
       MAX( xf_user_group.display_style_priority ) AS display_style_priority 
FROM xf_user_group_relation
     INNER JOIN xf_user_group ON xf_user_group_relation.user_group_id = xf_user_group.user_group_id
     INNER JOIN xf_user_field_value ON xf_user_group_relation.user_id = xf_user_field_value.user_id
WHERE xf_user_group.display_style_priority >= 500 
      AND field_id = 'minecraft' 
      AND xf_user_group_relation.user_group_id NOT IN(21,22)
GROUP BY xf_user_group_relation.user_id, 
      xf_user_field_value.field_value;

这些群组位于xf_user_group,结构为:

user_group_id            int(10)        AUTO_INCREMENT
title                    varchar(50)
display_style_priority   int(10)
user_css                 text
user_title               varchar(100)

4 个答案:

答案 0 :(得分:1)

MySql错误地允许您聚合值而不指定GROUP BY中的所有非聚合。因此,它自己选择要为user_group_id显示的值。 要获得所需的结果,必须为每个用户获得最大的display_style_priority,然后将user_id和value连接回原始表以过滤它们。您可以使用两种表单,加入

SELECT *
FROM xf_user_group_relation
     INNER JOIN xf_user_group 
        ON xf_user_group_relation.user_group_id = xf_user_group.user_group_id
     INNER JOIN xf_user_field_value 
        ON xf_user_group_relation.user_id = xf_user_field_value.user_id
     INNER JOIN
     (
       SELECT r2.user_id, MAX(g2.display_style_priority) display_style_priority
         FROM xf_user_group_relation r2
        INNER JOIN xf_user_group g2 
           ON r2.user_group_id = g2.user_group_id
        GROUP BY r2.user_id
     ) maxDSP
        ON xf_user_group_relation.user_id = maxDSP.user_id
       AND xf_user_group.display_style_priority = maxDSP.display_style_priority
WHERE xf_user_group.display_style_priority >= 500 
      AND field_id = 'minecraft' 
      AND xf_user_group_relation.user_group_id NOT IN(21,22)

并且与子查询中的最大值进行比较:

SELECT *
FROM xf_user_group_relation
     INNER JOIN xf_user_group 
        ON xf_user_group_relation.user_group_id = xf_user_group.user_group_id
     INNER JOIN xf_user_field_value 
        ON xf_user_group_relation.user_id = xf_user_field_value.user_id
WHERE xf_user_group.display_style_priority =
      (SELECT MAX(g2.display_style_priority) 
         FROM xf_user_group_relation r2
        INNER JOIN xf_user_group g2 
           ON r2.user_group_id = g2.user_group_id
        WHERE r2.user_id = xf_user_group_relation.user_id
      )
      AND xf_user_group.display_style_priority >= 500 
      AND field_id = 'minecraft' 
      AND xf_user_group_relation.user_group_id NOT IN(21,22)

现场演示位于Sql Fiddle

答案 1 :(得分:0)

您可以添加order by

ORDER BY xf_user_group_relation.user_id DESC

答案 2 :(得分:0)

此查询是否将具有最低ID的组配对并说它具有最高的display_style_priorty?

如果是这样,子查询可以为你处理,但我不确定你得到的结果是什么,以及所需的结果是什么

答案 3 :(得分:0)

准确地说,这会使每个用户的(user_id, field_value)的显示优先级最高的组返回。我认为这就是你想要的:

SELECT r.user_id, 
       x.field_value,
       r.user_group_id, 
       x.max_disp AS display_style_priority
FROM (
    SELECT r.user_id, v.field_value, max(g.display_style_priority) AS max_disp
    FROM   xf_user_group_relation r
    JOIN   xf_user_field_value    v USING (user_id)
    JOIN   xf_user_group          g USING (user_group_id)
    WHERE  g.display_style_priority >= 500 
    AND    v.field_id = 'minecraft' 
    AND    r.user_group_id NOT IN (21,22)
    GROUP  BY r.user_id, v.field_value
    )  x
JOIN  xf_user_group_relation r USING (user_id)
JOIN  xf_user_group g ON g.display_style_priority = x.max_disp
                     AND g.user_group_id = r.user_group_id

如果用户可以拥有多个具有相同display_style_priority的组,则每个(user_id, field_value)可以返回多行,共享相同的最大显示优先级。


其他RDBMS(如PostgreSQL,MSSQL或Oracle)具有窗口函数,可以从根本上简化此类任务。

在PostgreSQL中,您的查询可以这样工作:

SELECT DISTINCT
       r.user_id
      ,v.field_value
      ,last_value(g.user_group_id) OVER w AS user_group_id
      ,last_value(g.display_style_priority) OVER w AS display_style_priority 
FROM   xf_user_group_relation r
JOIN   xf_user_field_value    v USING (user_id)
JOIN   xf_user_group          g USING (user_group_id)
WHERE  g.display_style_priority >= 500 
AND    v.field_id = 'minecraft' 
AND    r.user_group_id NOT IN (21,22)
WINDOW w AS (PARTITION BY r.user_id, v.field_value
             ORDER BY g.display_style_priority);

Introduction to window functions in the PostgreSQL manual.