MySQL中沒有Rank排名函數(shù)游盲,當我們需要查詢排名時,只能使用MySQL數(shù)據(jù)庫中的基本查詢語句來查詢普通排名蛮粮。盡管如此益缎,可不要小瞧基礎而簡單的查詢語句,我們可以利用其來達到Rank函數(shù)一樣的高級排名效果然想。
在這里我用一個簡單例子來實現(xiàn)排名的查詢:
首先我們先創(chuàng)建一個我們需要進行高級排名查詢的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);
1、在MySQL中實現(xiàn)Rank普通排名函數(shù)
在這里变泄,我們希望獲得一個排名字段的列令哟,以及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
,但它會處理兩個查詢:
SET @curRank := 0;
SELECT pid, name, age, @curRank := @curRank + 1 AS rank
FROM players
ORDER BY age
2表窘、查詢以降序排列
首要按age的降序排列典予,其次按name進行排列,只需修改查詢語句加上ORDER BY
和 DESC
以及列名即可乐严。
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 |
3瘤袖、在MySQL中實現(xiàn)Rank普通并列排名函數(shù)
現(xiàn)在,如果我們希望為并列數(shù)據(jù)的行賦予相同的排名昂验,則意味著那些在排名比較列中具有相同值的行應在MySQL中計算排名時保持相同的排名(例如在我們的例子中的age
)捂敌。為此,我們使用了一個額外的變量既琴。
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 |
如上所示占婉,具有相同數(shù)據(jù)和排行的兩行或多行,它們都會獲得相同的排名甫恩。玩家Andre, Vino, John 和Tom都有相同的age逆济,所以他們排名并列第二。下一個最高age的玩家(Brian)排名第3。這個查詢相當于MSSQL和ORACLE 中的DENSE_RANK()函數(shù)奖慌。
4抛虫、在MySQL中實現(xiàn)Rank高級并列排名函數(shù)
當使用RANK()函數(shù)時,如果兩個或以上的行排名并列简僧,則相同的行都會有相同的排名建椰,但是實際排名中存在有關系的差距。
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()函數(shù)蹦浦。
| 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()之間的區(qū)別颁湖,并且知道在哪里應使用哪個查詢來獲取MySQL中的rank函數(shù)宣蠕。謝謝。
via http://fellowtuts.com/mysql/query-to-obtain-rank-function-in-mysql