MySQL中没有Rank排名函数,当咱们须要查询排名时,只能使用MySQL数据库中的基本查询语句来查询普通排名。尽管如此,可不要小瞧基础而简单的查询语句,咱们能够利用其来达到Rank函数同样的高级排名效果。mysql
在这里我用一个简单例子来实现排名的查询:sql
首先咱们先建立一个咱们须要进行高级排名查询的players
表,数据库
CREATE TABLE `players` ( `pid` int(2) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `age` int(2) NOT NULL, PRIMARY KEY (`pid`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO `players` (`pid`, `name`, `age`) VALUES (1, 'Samual', 25), (2, 'Vino', 20), (3, 'John', 20), (4, 'Andy', 22), (5, 'Brian', 21), (6, 'Dew', 24), (7, 'Kris', 25), (8, 'William', 26), (9, 'George', 23), (10, 'Peter', 19), (11, 'Tom', 20), (12, 'Andre', 20);
在这里,咱们但愿得到一个排名字段的列,以及age
的升序排列。因此咱们的查询语句将是:函数
SELECT pid, name, age, @curRank := @curRank + 1 AS rank FROM players p, ( SELECT @curRank := 0 ) q ORDER BY age | PID | NAME | AGE | RANK | |-----|---------|-----|------| | 10 | Peter | 19 | 1 | | 12 | Andre | 20 | 2 | | 2 | Vino | 20 | 3 | | 3 | John | 20 | 4 | | 11 | Tom | 20 | 5 | | 5 | Brian | 21 | 6 | | 4 | Andy | 22 | 7 | | 9 | George | 23 | 8 | | 6 | Dew | 24 | 9 | | 7 | Kris | 25 | 10 | | 1 | Samual | 25 | 11 | | 8 | William | 26 | 12 |
要在mysql中声明一个变量,你必须在变量名以前使用@
符号。FROM子句中的(@curRank := 0)
部分容许咱们进行变量初始化,而不须要单独的SET
命令。固然,也可使用SET
,但它会处理两个查询:code
SET @curRank := 0; SELECT pid, name, age, @curRank := @curRank + 1 AS rank FROM players ORDER BY age
首要按age的降序排列,其次按name进行排列,只需修改查询语句加上ORDER BY
和 DESC
以及列名便可。get
SELECT pid, name, age, @curRank := @curRank + 1 AS rank FROM players p, ( SELECT @curRank := 0 ) q ORDER BY age DESC, name | PID | NAME | AGE | RANK | |-----|---------|-----|------| | 8 | William | 26 | 1 | | 7 | Kris | 25 | 2 | | 1 | Samual | 25 | 3 | | 6 | Dew | 24 | 4 | | 9 | George | 23 | 5 | | 4 | Andy | 22 | 6 | | 5 | Brian | 21 | 7 | | 12 | Andre | 20 | 8 | | 3 | John | 20 | 9 | | 11 | Tom | 20 | 10 | | 2 | Vino | 20 | 11 | | 10 | Peter | 19 | 12 |
如今,若是咱们但愿为并列数据的行赋予相同的排名,则意味着那些在排名比较列中具备相同值的行应在MySQL中计算排名时保持相同的排名(例如在咱们的例子中的age
)。为此,咱们使用了一个额外的变量。io
SELECT pid, name, age, CASE WHEN @prevRank = age THEN @curRank WHEN @prevRank := age THEN @curRank := @curRank + 1 END AS rank FROM players p, (SELECT @curRank :=0, @prevRank := NULL) r ORDER BY age | PID | NAME | AGE | RANK | |-----|---------|-----|------| | 10 | Peter | 19 | 1 | | 12 | Andre | 20 | 2 | | 2 | Vino | 20 | 2 | | 3 | John | 20 | 2 | | 11 | Tom | 20 | 2 | | 5 | Brian | 21 | 3 | | 4 | Andy | 22 | 4 | | 9 | George | 23 | 5 | | 6 | Dew | 24 | 6 | | 7 | Kris | 25 | 7 | | 1 | Samual | 25 | 7 | | 8 | William | 26 | 8 |
如上所示,具备相同数据和排行的两行或多行,它们都会得到相同的排名。玩家Andre, Vino, John 和Tom都有相同的age,因此他们排名并列第二。下一个最高age的玩家(Brian)排名第3。这个查询至关于MSSQL和ORACLE 中的DENSE_RANK()函数。function
当使用RANK()函数时,若是两个或以上的行排名并列,则相同的行都会有相同的排名,可是实际排名中存在有关系的差距。class
SELECT pid, name, age, rank FROM (SELECT pid, name, age, @curRank := IF(@prevRank = age, @curRank, @incRank) AS rank, @incRank := @incRank + 1, @prevRank := age FROM players p, ( SELECT @curRank :=0, @prevRank := NULL, @incRank := 1 ) r ORDER BY age) s
这是一个查询中的子查询。咱们使用三个变量(@incRank,@prevRank,@curRank)来计算关系的状况下,在查询结果中咱们已经补全了由于并列而致使的排名空位。咱们已经封闭子查询到查询。这个查询至关于MSSQL和ORACLE中的RANK()函数。基础
| PID | NAME | AGE | RANK | |-----|---------|-----|------| | 10 | Peter | 19 | 1 | | 12 | Andre | 20 | 2 | | 2 | Vino | 20 | 2 | | 3 | John | 20 | 2 | | 11 | Tom | 20 | 2 | | 5 | Brian | 21 | 6 | | 4 | Andy | 22 | 7 | | 9 | George | 23 | 8 | | 6 | Dew | 24 | 9 | | 7 | Kris | 25 | 10 | | 1 | Samual | 25 | 10 | | 8 | William | 26 | 12 |
在这里咱们能够看到,Andre,Vino,John和Tom都有相同的age,因此他们排名并列第二。下一个最高年龄的球员(Brian)排名第6,而不是第3,由于有4我的并列排名在第2。
好的,我但愿在这些例子后,能让你了解RANK()和DENSE_RANK()之间的区别,而且知道在哪里应使用哪一个查询来获取MySQL中的rank函数。谢谢。
原文地址: http://fellowtuts.com/mysql/query-to-obtain-rank-function-in-mysql
本文转自简书:在MySQL中实现Rank高级排名函数