在很多時候,都有排名這個功能,比如排行榜,並且還需要分頁的功能,一般可以再select的時候按照某一字段 oorder by XX desc,這樣limit 查找就可以得到排名信息,但是有時候是需要多表連接,或者是有一個隨機查看,在頁面上並不是按照排名升降序。這個時候就需要用SQL來實現排名。
先准備測試數據:
Table: CREATE TABLE `test` ( `Score` int(255) NOT NULL, `Name` varchar(255) NOT NULL, `Type` varchar(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of test -- ---------------------------- INSERT INTO `test` VALUES ('79', '張三', '數學'); INSERT INTO `test` VALUES ('69', '張三', '語文'); INSERT INTO `test` VALUES ('57', '張三', '英語'); INSERT INTO `test` VALUES ('81', '李四', '數學'); INSERT INTO `test` VALUES ('45', '李四', '語文'); INSERT INTO `test` VALUES ('84', '李四', '英語'); INSERT INTO `test` VALUES ('15', '王五', '數學'); INSERT INTO `test` VALUES ('47', '王五', '語文');

如果要查詢數學科目的排名,可以用以下sql語句:
select a.*,@a := @a+1 as rank from test a,(select @a:=0) b where type=' 數學 ' order by a.score desc;
結果如下:

也就是使用a變量,按照order by的順序遞增。這個很好理解,但是如果有分組排序的需求呢?
例如在Test表中,要用一條sql查出數學、語文、英語三個科目各自的排名呢?
首先可以想到方法還是類似查詢單科排名,先將所有記錄按照科目、得分排序,Order by Type,Score。然后自定義變量遞增,但是關鍵就在於需要判斷科目的記錄有多少條,也即自定義變量歸零重新遞增的臨界點。
簡單排名使用一個變量a,那么在分組排序中可以考慮使用兩個變量,a、b
先執行如下sql
select a.* from test a order by type,score;

現在加上排名,先使用一個變量看得到什么效果:
select a.*,(@a := @a + 1) as rank from test a,(select @a := 0) b order by type,score;

現在排名並沒有按照科目的不同重新計算,我們只要解決排名何時歸0,就可以得到分組排序的結果了。
再加一個中間變量nowType試試?讓這個中間變量nowType等於Type(科目),只要下一條記錄與這個中間變量nowType相等,rank就加1,不相等的話,rank就歸零,來看下這條SQL:
select a.*,@lastType := @nowType,@ nowType:= a.type,if(@lastType = @nowType,@rank := @rank + 1,@rank := 0) as rank from test a,(select @a := 0,@ nowType:= 0,@rank := 0) b order by type,score;
現在看來是不是比較簡單了,lastType用於記錄上一條記錄的Type,nowType是當前記錄的Type,只要nowType=lastType,就說明是同一科目,rank加+,反之,rank歸零。

但是我們看到同樣是將rank初始化為0,為什么上面是從1開始,而這次是從0開始呢?再分析下sql,在第一條記錄的時候,lastType=0.而nowType=數學,肯定不相等,所以輸出0,rank從0開始,只要將rank初始化為1就好了。
select a.*,@lastType := @temp,@temp := a.type,if(@lastType = @temp,@rank := @rank + 1,@rank := 1) as rank from test a,(select @a := 0,@temp := 0,@rank := 0) b order by type,score;

