天天看點

mysql實作row_number()、rank()、dense_rank()函數功能

最近部門換了一款BI工具,因為要根據篩選條件動态選取TOP10、實作排序排名功能,需要在BI工具中寫mysql資料庫的腳本,因為要實作ow_number()、rank()、dense_rank()函數功能,看了網上的一些資料,感覺腳本和資料示例有點出入,在這裡根據一個簡單的臨時表做一下總結。

臨時表名:tmp_ss

示例資料:

mysql實作row_number()、rank()、dense_rank()函數功能

可以看到store_name是有重複值的,可以用這個字段的排名來看dense_rank()、rank()的實作。

(1) row_number()實作方法

SELECT  store_name 
,@rank := @rank +1 
,@val := store_name 
FROM tmp_ss , (SELECT @val := '' , @rank := 0 ) t1 
ORDER BY store_name
; 

           

這裡@val、@rank是mysql的變量表示方法,我們這裡先看運作結果:

mysql實作row_number()、rank()、dense_rank()函數功能

我們看到第二列也就是排序列是連續的,即使store_name相同。我們可以感受一下這兩個變量值變化的規律,就好比是tmp_ss排序之後,有一個遊标周遊每一行,然後沒周遊一行,@rank自加1,然後會把每行store_name的值傳給@val;這個和oracle中存儲過程的遊标是非常類似的。

(2)dense_rank()實作方法

SELECT  
	 @val
	,store_name 
	,@rank := IF(@val = store_name,@rank ,@rank +1) 
	,@val := store_name 
FROM tmp_ss , (SELECT @val := '' , @rank := 0 ) t1 
ORDER BY store_name
;
           

運作結果:

mysql實作row_number()、rank()、dense_rank()函數功能

我們可以看到store_name相同時,排名是相同的,且排名數字不跳躍,排名n後面跟的一定是n或者n+1。這裡第一列在實際寫生産腳本的時候是不必要的,這裡列出來隻是為了大家能夠清楚的看到,當運作sql時,剛開始這個變量是沒有值的,然後@val := store_name這個代碼把每行store_name的傳給@val,從上向下看每一行,我們的非常清晰的感受到這個程式的運作過程。

(3)rank()實作方法

SELECT store_name 
,@rownum := @rownum +1 
,@rank := IF(@val = store_name,@rank ,@rownum) 
,@val := store_name 
FROM tmp_ss , (SELECT @val := '' , @rank := 0 ,@rownum := 0 ) t1 
ORDER BY store_name
; 
           

運作結果:

mysql實作row_number()、rank()、dense_rank()函數功能

我們看到,實作rank()的時候用到了3個變量,比上面多了一個@rownum變量,這個變量沒周遊一行就會自加1,跟行号一樣,這樣的話就能實作排名的跳躍。怎麼了解呢?我們複習下dense_rank()和rank()的差別,舉個例子如果有20行資料進行排名,排序列有重複值,那麼dense_rank()排名的最大序号小于20,rank()排名的最大序号一定是20,也就是說dense_rank()總排名會減少,而rank()總排名不減少。

下面重點來看@rank := IF(@val = store_name,@rank ,@rownum) 這段判斷語句,首先上一行的store_name是存在@val中的,如果@val跟遊标所在的目前行store_name相同,則取@rank值,即與上一樣的排名相同,如果不相同,那麼就取這行的行号作為排名。

總結: 這篇文章重點講解了mysql排名的具體實作方法,表達能力有限,而且例子乍一看可能會感覺有些繞,讀者不妨建臨時表親手運作一下示例代碼。

需要注意,在實作排序的時候,隻能有2個表關聯,且第二表是用于實作排序的表。

類似于

t1

left join t2 on xxx = xxx

left join (SELECT @val := ‘’ , @rank := 0 ) t3

on 1 =1

這樣多表關聯的情況,親測并不能實作排序的功能。

繼續閱讀