? ? ? ?在面試過程中窗口函數(shù)的應(yīng)用可謂是數(shù)不勝數(shù),前提你要知道什么是窗口函數(shù),最常用的窗口函數(shù)有哪些?語法是什么?分別用的場景是什么?今天會以這三個問題開始我們今天的學(xué)習(xí)
什么是窗口函數(shù)?
? ? ? ?所謂的窗口函數(shù)就是動態(tài)處理數(shù)據(jù)的一類函數(shù),也叫做“OLAP”函數(shù),可以對數(shù)據(jù)庫數(shù)據(jù)進行實時分析處理,“窗口函數(shù)”由兩部分組成:分析函數(shù)+窗口函數(shù):
--模板
函數(shù)名(字段名) over(partition by xxx,yyy order by zzz)
--詳細(xì)介紹
分析函數(shù) over (partition by "要分組的列")
order by "要排序的列"
rows between "開始的行" and "結(jié)束的行")
? ? ? ?over()部分才是“窗口函數(shù)”,只不過因為它的特點大家都這樣叫,其作用就是劃定窗口,分析函數(shù)的作用是在窗口內(nèi)對記錄進行統(tǒng)計
over函數(shù)中有3個參數(shù):
- partition by
? ? ? ?其表示的是分區(qū)或者分組,可以理解成為group by,但是低位有所不同,如果partition by 和group by 后的字段相同,partition by 就會失效,因為group by先分組(劃分窗口),如果字段相同則partition by 就沒有可分的了
如果partition函數(shù)想要做到像group by一樣的效果,必須要和distinct關(guān)鍵字進行去重
- order by
? ? ? ?表示排序,排序、累加都是有排序的操作在里面,根據(jù)設(shè)么條件排名、根據(jù)什么條件進行累加,order by后面可以跟一個字段也可以跟多個字段,位置優(yōu)先,越在前面排序的優(yōu)先級越高,默認(rèn)“asc(升序)” 小-大,desc(降序)大-小
- rows between "開始的行" and "結(jié)束的行"
這部分是控制窗口大小的地方,一般默認(rèn)就行,也不會進行書寫,但是也可以自定義窗口大小:
proceding:往前
following:往后
unbounded:無窮盡的
current row:當(dāng)前行
unbounded proceding:往前所有行
unbounded following:往后所有行
?舉幾個例子方便理解:
rows between 2 preceding and current row --取當(dāng)前行和前2行,這個可用于求移動平均
rows between current row and 2 following --取當(dāng)前行和后2行,這個可用于求移動平均
rows between unbounded preceding and current row --取當(dāng)前行和之前所有行,這個可用于求累加;如果沒有寫rows between參數(shù),則默認(rèn)的窗口就是這個范圍
rows between current row and unbounded following --取當(dāng)前行和之后所有行
rows between 2 preceding and 2 following --取當(dāng)前行的前面2行和下面2行,總共5行,這個可用于求移動平均
動態(tài)窗口的動態(tài)演示圖:
?接下來我們來講一般常用的三種窗口函數(shù):
我們現(xiàn)在有一個班級的成績數(shù)據(jù),要求按規(guī)定進行查詢:
CREATE TABLE class(
cid VARCHAR(10),
NAME VARCHAR(20),
grades INT
)
DROP TABLE class
INSERT INTO class (cid,NAME,grades) VALUES('1','路飛',60),('1','鳴人',70),('1','佐助',75),('1','蕭炎',80),('1','唐三',90),('1','奕星',91),('2','霸天虎',50),('2','玉環(huán)',60),('2','索隆',66),('2','墨子',85),('2','鐵甲小寶',89)
? ? ? ?假如動漫學(xué)院期末成績出來了,老師讓你幫根據(jù)一定的規(guī)則去查詢成績,你可以幫忙完成這個工作么?
- 聚合類的窗口函數(shù) sum() over()(舉例)? ? ? ?count\avg\max\min
情境一:現(xiàn)在要求讓每位同學(xué)后面都新增一列各自班級的總分
SELECT*,
SUM(grades) OVER (PARTITION BY cid) AS "班級總分"
FROM class
?情境二:計算同一個班級內(nèi),每個同學(xué)和比他分?jǐn)?shù)低的總分是多少?
SELECT*,
SUM(grades) OVER (PARTITION BY cid ORDER BY grades) AS "累加分?jǐn)?shù)"
FROM class
SELECT*,
SUM(grades) OVER (PARTITION BY cid ORDER BY grades ROWS BETWEEN unbounded preceding AND current ROW ) AS "累加分?jǐn)?shù)"
FROM class
?這條SQL語句的效果和上面那條SQL語句效果一致,不寫的話默認(rèn)就是這個范圍
- 排序類的窗口函數(shù)
-
row_number(順序,相同的不做特別處理)
假如現(xiàn)在讓你將1、2班的成績排個名,從低到高,你有沒有什么好的辦法?|SELECT *, ROW_NUMBER() OVER (PARTITION BY cid ORDER BY grades DESC) AS "成績排名" FROM class;
-
rank(相同的做特別處理,會進行占位)
? ? ? ?在拍完名之后,發(fā)現(xiàn)相同成績的同學(xué)居然排名不一樣,這又讓老師犯難了,怎么樣才能使得相同成績的同學(xué)擁有相同的排名SELECT *, RANK() OVER (PARTITION BY cid ORDER BY grades DESC) AS "成績排名" FROM class;
-
dense_rank(相同的做特殊處理,不占位)
? ? ? ?但是又新出現(xiàn)了一個問題,相同的成績的排名確實排名也相同了,但是后面的那個同學(xué)居然是從3開始的,自動的將2跳過了,這也是我們不希望看到的
?SELECT *, DENSE_RANK() OVER (PARTITION BY cid ORDER BY grades DESC) AS "成績排名" FROM class;
- 偏移類的、跨行的窗口函數(shù)
- lag(后面)
如果現(xiàn)在又有一個任務(wù),讓每位同學(xué)知道比自己低1(N)名的同學(xué)的成績
?SELECT*, LAG(grades,1) OVER (PARTITION BY cid ORDER BY grades) AS "低一名的成績" FROM class
但是最后的結(jié)果中卻出現(xiàn)了null值,我們想如果查不到數(shù)據(jù)結(jié)果置為0,該怎么去實現(xiàn)呢?
LAG(字段,差值,默認(rèn)值)
?SELECT*, LAG(grades,1,0) OVER (PARTITION BY cid ORDER BY grades) AS "低一名的成績" FROM class
- 2.lead(前面)
?如果現(xiàn)在又有一個任務(wù),讓每位同學(xué)知道比自己高1(N)名的同學(xué)的成績
SELECT*,
LEAD(grades,1,0) OVER (PARTITION BY cid ORDER BY grades) AS "高一名的成績"
FROM class
文章來源:http://www.zghlxwxcb.cn/news/detail-662367.html
?最常用的窗口函數(shù)已經(jīng)介紹完了,學(xué)習(xí)SQL的路上一路有我?。?!文章來源地址http://www.zghlxwxcb.cn/news/detail-662367.html
到了這里,關(guān)于SQL助你面大廠(窗口函數(shù))的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!