MySQL數(shù)據(jù)庫專欄:
簡書:http://www.reibang.com/nb/42057860
知乎:https://zhuanlan.zhihu.com/791072385mysql
一展父、窗口函數(shù)概念
窗口函數(shù)又叫做分析函數(shù)坪仇,在Oracle中已經(jīng)早就又了,這次MySQL從5.x升級到8.x其中一個特性就是開始支持窗口函數(shù)了魁亦。在MySQL不支持窗口函數(shù)之前,一直采用變量的方式來模擬窗口函數(shù)的實現(xiàn)奔则,雖然效率還行杏死,但是代碼看上去并不簡單。
首先要理解窗口函數(shù)是干什么用的光督?當(dāng)我們處理既要分組時,又要對分組內(nèi)的數(shù)據(jù)進(jìn)行排序的時候塔粒,我們就可以使用窗口函數(shù)结借。
窗口函數(shù)和普通聚合函數(shù)很容易混淆,二者區(qū)別如下:
- 聚合函數(shù)是將多條記錄聚合為一條卒茬;而窗口函數(shù)是每條記錄都會執(zhí)行船老,有幾條記錄執(zhí)行完還是幾條咖熟。
- 聚合函數(shù)也可以用于窗口函數(shù)中。
二努隙、具體例子
通常我們一般使用的比較多的是窗口函數(shù)中的序號函數(shù):row_number() / rank() / dense_rank(),那這三個函數(shù)能起到的作用如下:
//例子來自leetCode中高贊題解(TopN分組排序問題)
https://leetcode-cn.com/problems/department-top-three-salaries/solution/tu-jie-sqlmian-shi-ti-jing-dian-topnwen-ti-by-houz/
//還可以使用over(partition by 分組 order by 字段)實現(xiàn)先分組后排序
select *,
rank() over (order by 成績 desc) as ranking,
dense_rank() over (order by 成績 desc) as dese_rank,
row_number() over (order by 成績 desc) as row_num
from 班級;
?得到結(jié)果:
從上面的結(jié)果可以看出:
1)rank函數(shù):這個例子中是5位辜昵,5位荸镊,5位,8位堪置,也就是如果有并列名次的行躬存,會占用下一名次的位置。比如正常排名是1舀锨,2岭洲,3,4坎匿,但是現(xiàn)在前3名是并列的名次盾剩,結(jié)果是:1,1替蔬,1告私,4。
2)dense_rank函數(shù):這個例子中是5位承桥,5位驻粟,5位,6位凶异,也就是如果有并列名次的行蜀撑,不占用下一名次的位置。比如正常排名是1剩彬,2酷麦,3,4喉恋,但是現(xiàn)在前3名是并列的名次贴铜,結(jié)果是:1,1瀑晒,1绍坝,2。
3)row_number函數(shù):這個例子中是5位苔悦,6位轩褐,7位,8位玖详,也就是不考慮并列名次的情況把介。比如前3名是并列的名次勤讽,排名是正常的1,2拗踢,3脚牍,4。
三巢墅、總結(jié)
面對一些既要分組又要排序的TOP N問題诸狭,我們可以使用窗口函數(shù)快速得出結(jié)果.
# topN問題 sql模板
select *
from (
select *,
row_number() over (partition by 要分組的列名
order by 要排序的列名 desc) as 排名
from 表名) as a
where 排名 <= N;