在MySQL中按组排名

3

我有一个包含以下内容的表格:

name
-------
Michael
Michael
Michael
Michael
John
John
John
Alex
Alex

我需要对它们进行排名:

name    | rank
--------|------
Michael |1
Michael |2
Michael |3
Michael |4
John    |1
John    |2
John    |3
Alex    |1
Alex    |2

我该如何执行这个操作?

2个回答

6

简单易懂,

CREATE TABLE customer (
name CHAR(30) NOT NULL,
rank MEDIUMINT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (name,rank)) ENGINE=MyISAM;

INSERT INTO customer (name) VALUES
('Michael'),('Michael'),('John'),('Alex'),('Michael'),('John');

SELECT * FROM customer ORDER BY name,rank;

是的,现在你有了一个简单的数字序列。OP想要每个名称的序列,而不是每个表的序列。 - Marc B
2
它将按照他想要的方式工作,仅根据名称添加序列。试一试吧。 - Yatin Trivedi
这是一个非常棒的技巧。我已经为了这个特定的答案在 Stack Overflow 上搜索了半打次。 - BringMyCakeBack
这既晦涩难懂又非常精彩!对于实际应用,也可以使用临时表来完成。 - coatesap
1
如果表格也有一个自增的主键 Id 列,会怎样呢? - elcool
很棒的解决方案,但MySQL没有一个可用的Rank()函数是不可原谅的,所以我们不得不采取这样奇怪的解决方案(请注意,如果您不包括ENGINE=MyISAM,它将无法工作)。 - EliSquared

5

MySQL本身没有直接实现这个功能的方法,但你可以通过一些技巧来实现:

SET @prev := null;

SET @cnt := 1;

SELECT name, IF(@prev <> name, @cnt := 1, @cnt := @cnt + 1) AS rank, @prev := name
FROM yourtable
ORDER BY name

这种事情在客户端应用程序中更容易完成,使用相同的基本逻辑即可。

由于空值的存在,Michael 的排名从2开始(2、3、4、5)。如果我设置@prev:='string',则结果是正确的。谢谢。 - user1889867
Marc,请查看下面的评论。在MySQL中完成这个任务并不是很难。 - Yatin Trivedi
这种方法不可靠,因为在单个SELECT语句中读取@prev并写入它的计算顺序是未定义的。请参阅http://dev.mysql.com/doc/refman/5.5/en/user-variables.html。 - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接