Mysql分组排名

时间:2013-02-01 17:25:09

标签: mysql greatest-n-per-group

this question相关。

实际上,以免我们要解决 mysql 中的分组排名问题。我们有一个表,每行代表一个实体,属于一个组。我们希望根据每个组的属性为每个实体分配排名。稍后我们可以对等级进行各种操作,比如要求每个组的前10个实体也满足另一个条件,等等。

例如,实体可以是根据他们喜欢的编程语言属于不同“组”的程序员。然后每个程序员都有声誉(让我们说在论坛中)。我们想要添加一个额外的字段,这个字段将是程序员根据声望下降的排名。我们希望为每个小组独立完成此任务。

gid | repu | name |
1       1    john
1       3    anna
2       2    scot
2       1    leni

成为

gid | repu | name | rank
1       3    anna      1
1       1    john      2
2       2    scot      1
2       1    leni      2

现在我们还要求我们不想使用基于会话变量的解决方案。是的,它们工作得很好但是它们显然违反了mysql的要求,即不在同一语句中读取和写入会话变量。 (See here

现在this post中建议的解决方案

-- SOL #1 (SELF-JOIN)
SELECT a.*, count(*) as row_number FROM test a
JOIN test b ON a.gid = b.gid AND a.repu <= b.repu
GROUP BY a.gid, a.repu

这件事几乎就是这样。我有一些问题,这是合法的SQL还是违反任何标准或mysql怪癖?是否保证它可以在mysql上运行?

我读到here的另一个解决方案是,对我来说这更像是一个黑魔法,但看起来更优雅

-- SOL #2 (SUBQUERY)
SELECT t.* ,
    ( SELECT COUNT(*) + 1
        FROM test
        WHERE repu > t.repu AND gid = t.gid 
    ) AS rank
FROM test AS t
ORDER BY gid ASC, rank ASC  

这使用引用外部表的子查询,并且也可以使用。有人能解释一下这个有用吗?

此外,这里的问题与解决方案#1相同。

加上评估两个建议解决方案的性能/兼容性的任何评论。

编辑:附加方法,供参考

来自this post会话变量方法的一种变体。 警告:这是我想要避免的。请注意,在单个语句中,读取@rand和@partition会话变量(在WHEN和THEN之后的情况下)并写入(在THEN AND ELSE之后的CASE中以及初始化变量的下一个子查询中)。

-- SOL #3 (SESSION VARIABLES / ANTIPATTERN)
SELECT t.*, ( CASE gid
             WHEN @partition THEN @rank := @rank + 1 
             ELSE @rank := 1 AND @partition := gid ) AS rank
FROM test t, 
    (SELECT @rank := 0, @partition := '') tmp
ORDER BY gid ASC, repu DESC

此外,这是一个基于集合的解决方案,相当复杂,由一位同事发布。

-- SOL #4 (SET BASED)
SELECT x.*, FIND_IN_SET(CONCAT(x.gid,':',x.repu), y.c) rank 
    FROM test x 
    JOIN (
        SELECT GROUP_CONCAT(DISTINCT CONCAT(gid,':',repu) ORDER BY gid, repu DESC) c 
        FROM test GROUP BY gid
    ) y ON FIND_IN_SET(CONCAT(x.gid,':',x.repu), y.c)

1 个答案:

答案 0 :(得分:0)

JOIN是合法的MYSQL语法。如果它不起作用,怀疑有人会将其标记为答案。

就子查询而言,它将比第一个解决方案更快。查看EXPLAIN PLAN将是理解这些查询执行情况的好主意。

还有另一种方法可以达到同样的目的: -

  • - SOL#3:在这篇文章中以30票回答:

ROW_NUMBER() in MySQL