在MySQL中實現(xiàn)Rank高級排名函數(shù)

MySQL中沒有Rank排名函數(shù),當(dāng)我們需要查詢排名時,只能使用MySQL數(shù)據(jù)庫中的基本查詢語句來查詢普通排名。盡管如此,可不要小瞧基礎(chǔ)而簡單的查詢語句,我們可以利用其來達(dá)到Rank函數(shù)一樣的高級排名效果。

在這里我用一個簡單例子來實現(xiàn)排名的查詢:

首先我們先創(chuàng)建一個我們需要進(jìn)行高級排名查詢的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)部分允許我們進(jìn)行變量初始化,而不需要單獨的SET命令。當(dāng)然,也可以使用SET,但它會處理兩個查詢:

SET @curRank := 0;
SELECT pid, name, age, @curRank := @curRank + 1 AS rank
FROM players
ORDER BY age

2、查詢以降序排列

首要按age的降序排列,其次按name進(jìn)行排列,只需修改查詢語句加上ORDER BYDESC以及列名即可。

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ù)的行賦予相同的排名,則意味著那些在排名比較列中具有相同值的行應(yīng)在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。這個查詢相當(dāng)于MSSQL和ORACLE 中的DENSE_RANK()函數(shù)。


4、在MySQL中實現(xiàn)Rank高級并列排名函數(shù)

當(dāng)使用RANK()函數(shù)時,如果兩個或以上的行排名并列,則相同的行都會有相同的排名,但是實際排名中存在有關(guān)系的差距。

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)來計算關(guān)系的情況下,在查詢結(jié)果中我們已經(jīng)補(bǔ)全了因為并列而導(dǎo)致的排名空位。我們已經(jīng)封閉子查詢到查詢。這個查詢相當(dāng)于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ū)別,并且知道在哪里應(yīng)使用哪個查詢來獲取MySQL中的rank函數(shù)。謝謝。

via http://fellowtuts.com/mysql/query-to-obtain-rank-function-in-mysql

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 分析函數(shù),也稱為窗口函數(shù),通常被認(rèn)為僅對數(shù)據(jù)倉庫SQL有用。使用分析函數(shù)的查詢,基于對數(shù)據(jù)行的分組來計算總量值。與...
    貓貓_tomluo閱讀 3,464評論 3 18
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,637評論 18 399
  • 2017.7.18第48天 星期二 晴 今天是兒子學(xué)英語,暑假班的最后一課,老師讓家長們?nèi)タ匆幌潞⒆觽儗W(xué)...
    鑫隆媽媽閱讀 293評論 0 1
  • 文/若杉 1、 不知道大家身邊是不是都有這樣的朋友: 你有需求他必定會盡心盡力的幫你; 一起逛街吃飯旅行,他也一定...
    若杉閱讀 1,416評論 34 36
  • 微信小程序1月9日正式上線,估計這幾天都是這個玩意刷屏了。自媒體,直播推出的時候都沒有這么大的影響力,但是依然...
    鄉(xiāng)本閱讀 12,204評論 0 0

友情鏈接更多精彩內(nèi)容