目前有一個表tb_rank(PlayerID,PlayerName,Score) PlayerID是Primary key(主鍵);sql
如今的需求是,但願在表tb_rank中再添加一列rankNum,這個rankNum記錄的是Score的排名spa
(根據分數作降序排列)。
.net
問題分析:code
通過分析,咱們能夠將此問題大概分解爲如下三個子問題:orm
(1) 在表tb_rank中增長一列rankNum;排序
ALTER TABLE tb_rank ADD rankNum INT;
(2)對錶tb_rank中的Score列進行降序排名,且將排名數值增長到被排序的元組中;get
初次執行排序可使用:it
SELECT PlayerID,PlayerName,Score,(@rank:=IFNULL(@rank,0)+1) rankNum FROM tb_rank ORDER BY Score DESC
廣泛使用的排序SQL爲:class
SET @rank:=0; SELECT PlayerID,PlayerName,Score,(@rank:=@rank+1) rankNum FROM tb_rank ORDER BY Score DESC
(3)用第2步的結果來更新新增列rankNum的值。變量
SET @rank:=0; UPDATE tb_rank,(select PlayerID,( @rank:=@rank+1) rankNum FROM tb_rank ORDER BY score DESC) temp_tb_rank SET tb_rank.rankNum=temp_tb_rank.rankNum WHERE tb_rank.PlayerID=temp_tb_rank.PlayerID;
排名的tb_rank表查詢返回的結果爲:
到此就實現了簡單的排名了。可是這裏存在一個問題,就是說當score相同的時候,
好比:
PlayerID是’12‘和’13‘以及’123456‘,它們的Score都是1000,
可是查詢出來的結果在排名上的呈現卻不一致。
這個是不合理的。下面第3節介紹一種解決方法。
實現思路:
產生第二步中一樣的分數出現不一樣的排名的問題,其根因是排名實現沒有考慮分數相同的狀況,
下面增長一個變量@preScore來保存產生當前元組時,上一個元組的分數;而後在生成排名的列,
根據當前元組的分數與上一個元組的分數大小進行比較,若是相等,那麼排名不變,不然排名加1。
編寫SQL語句須要注意一點,對變量@preScore的賦值須要放到排名列rankNum以後,
要讓其先生成排名,然後才能夠更新@preScore變量。
(從SQL語句的結果生成原理上看,SELECT語句中,寫在前面的列值是先生成,
寫在後面的列值是後獲得的。例如,下面的SELECT語句中,
PlayerID的位置放在最前面,那麼實際返回查詢結果的時候,是先獲取PlayerID的值的。)
<pre name="code" class="sql">SET @rank:=0; SET @preScore:=0;
SELECT PlayerID,( IF( @preScore<>Score,@rank :=@rank+1,@rank ) ) rankNum,@preScore:=Score FROM tb_rank ORDER BY score DESC
最後合成後的SQL語句爲:
SET @rank:=0; SET @preScore:=0; UPDATE tb_rank, (SELECT PlayerID,( IF( @preScore<>Score,@rank:=@rank+1,@rank ) ) rankNum,@preScore:=Score FROM tb_rank ORDER BY score DESC) temp_tb_rank SET tb_rank.rankNum=temp_tb_rank.rankNum WHERE tb_rank.PlayerID=temp_tb_rank.PlayerID;