三者的區(qū)別:
關(guān)于變量和if實現(xiàn)rank
SELECT s.score,
@rank_counter := @rank_counter + 1 連續(xù)排名,
IF(@pre_score = s.score, @cur_rank, @cur_rank := @rank_counter) ranking,
@pre_score := s.score
FROM score s, (SELECT @cur_rank :=0, @pre_score := NULL, @rank_counter := 0) r
ORDER BY s.score DESC;
邏輯:
要明白rank的排序邏輯把敢,如果是相同的數(shù)值钞楼,則并列排序,如果后面的值開始不一樣蒸眠,則跳躍排序漾橙,及1,1,3。那么有兩個地方需要注意:1楞卡、并列排序時霜运,讓排序值ranking保持不變,2蒋腮、跳躍排序時淘捡,讓ranking為該數(shù)字在正常排名的位置,及row_number的那個位置池摧。
那么在代碼里焦除,from中設(shè)置的三個變量:1、@cur_rank是實現(xiàn)并列排序和跳躍排序兩者的作彤,也即在rank開窗函數(shù)中最終實現(xiàn)的排名膘魄,2、@pre_score為上一段的得分竭讳,把他放在if的后面進行:=s.score的賦值创葡,比if里面的判斷=s.score慢一步,就是為了讓@pre_score等于上一段的分數(shù)绢慢,好來判斷是否為并列排序灿渴,3、@rank_counter在這里被賦值為0呐芥,然后在select的第一個是@rank_counter:=@rank_counter+1逻杖,也就是給score的每一個分數(shù)都給一個連續(xù)排名,相當(dāng)于row_number思瘟,他在這里的作用是為了給rank進行跳躍時得到他本來所處的位置數(shù)字荸百。
執(zhí)行完from中的代碼以后,開始執(zhí)行select滨攻,注意order by是在select的后面執(zhí)行的够话,但是賦值一直都是最后執(zhí)行的,所以這段代碼里光绕,想篩選出score以后女嘲,進行order by排序,然后再進行相應(yīng)的賦值诞帐。
在if函數(shù)里欣尼,第一步,@pre_score為null,不等于score的第一個值99愕鼓,所以為假钙态,執(zhí)行@cur_rank:=@rank_counter,得到1菇晃,然后再if的后面册倒,@pre_score被賦值為score,此時@pre_score=99磺送;第二步驻子,@pre_score的98不等于score的98,為假估灿,繼續(xù)得到@cur_rank:=@rank_counter,得到2崇呵,同樣第三步得到3,到了第四步馅袁,得到4演熟,重點第5步,此時@pre_score=上一段的分數(shù)等于89司顿,判斷時,@pre_score也是等于此時這一段的score的89時兄纺,為真大溜,返回@cur_rank,為4,這樣按照同樣的邏輯向后執(zhí)行估脆。
想明白它的邏輯钦奋,再設(shè)計相應(yīng)變量來實現(xiàn)目的。
對于下表進行相關(guān)計算疙赠。
一付材、不分組的情況下的rank/dense_rank/row_number
1、(1)連續(xù)排名row_number() over(order by)
對表中的所有的分數(shù)進行位置排名圃阳,沒有并列名次的情況
SELECT
score,
row_number ( ) over ( ORDER BY score DESC ) ranking
FROM
score;
(2)利用變量@和if來實現(xiàn)上面的開窗函數(shù)
SELECT
score,
@i := @i + 1 ranking
FROM
score,
( SELECT @i := 0 ) ranking
ORDER BY
score DESC;
2厌衔、(1)并列跳躍排名rank() over(order by)
SELECT
score,
rank ( ) over ( ORDER BY score DESC ) ranking
FROM
score;
(2)利用變量@和if來實現(xiàn)上面的開窗函數(shù)
思路:如果分數(shù)一樣,則排名相同捍岳,如果后面的分數(shù)不同富寿,則排名為該值在該表中本來的排名位置。
SELECT s.score,
@rank_counter := @rank_counter + 1 連續(xù)排名,
IF(@pre_score = s.score, @cur_rank, @cur_rank := @rank_counter) ranking,
@pre_score := s.score
FROM score s, (SELECT @cur_rank :=0, @pre_score := NULL, @rank_counter := 0) r
ORDER BY s.score DESC;
(3)使用case when來實現(xiàn)上面的開窗函數(shù)
SELECT
s.score,
@rank_counter := @rank_counter + 1 連續(xù)排名,
( CASE WHEN @pre_score = s.score THEN @cur_rank
WHEN @pre_score := s.score THEN @cur_rank := @rank_counter END ) ranking
FROM
score s,
( SELECT @pre_score := NULL, @cur_rank := 0, @rank_counter := 0 ) ranking
ORDER BY
score DESC;
3锣夹、(1)并列連續(xù)排名dense_rank() over(order by)
select score,
dense_rank() over(order by score desc) ranking
from score;
(2)利用變量@和if來實現(xiàn)上面的開窗函數(shù)
SELECT
score,
IF
( @pre_score = score, @cur_rank, @cur_rank := @cur_rank + 1 ) ranking,
@pre_score := score
FROM
score,
( SELECT @pre_score := NULL, @cur_rank := 0 ) ranking
ORDER BY
score DESC;
(3)利用case when來實現(xiàn)上面的開窗函數(shù)
SELECT
score,
( CASE WHEN @pre_score = score THEN @cur_rank WHEN @pre_score := score THEN @cur_rank := @cur_rank + 1 END ) ranking
FROM
score,
( SELECT @pre_score := NULL, @cur_rank := 0 ) ranking
ORDER BY
score DESC;
二页徐、分組的情況下的rank/dense_rank/row_number
1、(1)連續(xù)排名row_number() over(partition by order by)
SELECT
course_id,
score,
row_number ( ) over ( PARTITION BY course_id ORDER BY score DESC ) ranking
FROM
score
ORDER BY
course_id;
(2)使用變量@和if實現(xiàn)上面的開窗函數(shù)
SELECT
course_id,
score,
IF
( @pre_course_id = course_id, @cur_rank := @cur_rank + 1, @cur_rank := 1 ) ranking,
@pre_course_id := course_id
FROM
score,
( SELECT @pre_course_id := NULL, @cur_rank := 0 ) t
ORDER BY
course_id ASC,
score DESC;
2银萍、(1)并列跳躍排名rank() over(partition by order by)
SELECT
course_id,
score,
rank ( ) over ( PARTITION BY course_id ORDER BY score DESC ) ranking
FROM
score;
(2)利用變量和if來實現(xiàn)上面的開窗函數(shù)
SELECT
course_id,
score,
IF
( @pre_course_id = course_id, @rank_count := @rank_count + 1, @rank_count := 1 ) t1, #輔助列变勇,組內(nèi)連續(xù)排名
IF
( @pre_course_id = course_id,
IF( @pre_score = score, @cur_rank, @cur_rank := @rank_count ),
@cur_rank := 1
) ranking,
@pre_course_id := course_id ,
@pre_score := score
FROM
score,
( SELECT @pre_course_id := NULL, @pre_score := NULL, @cur_rank := 0, @rank_count := 1 ) t2
ORDER BY
course_id,
score DESC;
3、(1)并列連續(xù)排名dense_rank() over(partition by order by)
SELECT
course_id,
score,
dense_rank ( ) over ( PARTITION BY course_id ORDER BY score DESC ) ranking
FROM
score;
(2)利用變量@和if來實現(xiàn)上面的開窗函數(shù)
SELECT
course_id,
score,
IF
(
@pre_course_id = course_id,
IF
( @pre_score = score, @cur_rank, @cur_rank := @cur_rank + 1 ),
@cur_rank := 1
) ranking,
@pre_course_id := course_id,
@pre_score := score
FROM
score,
( SELECT @pre_score := NULL, @pre_course_id := NULL, @cur_rank := 0 ) t
ORDER BY
course_id,
score DESC;
整理自:https://blog.csdn.net/u011726005/article/details/94592866#41__134