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高級排名函數