sql server累计求和函数_SQL基础--SQL高级功能
一.窗口函數有什么用?
在日常工作中,經常會遇到需要在每組內排名,比如下面的業務需求:
排名問題:每個部門按業績來排名topN問題:找出每個部門排名前N的員工進行獎勵
面對這類需求,就需要使用sql的高級功能窗口函數了。
二.什么是窗口函數?
窗口函數,也叫OLAP函數(Online Anallytical Processing,聯機分析處理),可以對數據庫數據進行實時分析處理。
窗口函數的基本語法如下:
?窗口函數?語法中?窗口函數?的位置,可以放以下兩種函數:
1) 專用窗口函數,包括后面要講到的rank, dense_rank, row_number等專用窗口函數。
2) 聚合函數,如sum. avg, count, max, min等
因為窗口函數是對where或者group by子句處理后的結果進行操作,所以窗口函數原則上只能寫在select子句中。
接下來,就結合實例,給大家介紹幾種窗口函數的用法。
【經典排名問題】專用窗口函數rank
例如下圖,是班級表中的內容
如果我們想在每個班級內按成績排名,得到下面的結果。
得到上面結果的sql語句代碼如下:
select我們來解釋下這個sql語句里的select子句。
要求是“每個班級內按成績排名”,這句話可以分為兩部分:
1)每個班級內:按班級分組
partition by用來對表分組。在這個例子中,所以我們指定了按“班級”分組(partition by 班級)
2)按成績排名
order by子句的功能是對分組后的結果進行排序,默認是按照升序(asc)排列。在本例中(order by 成績 desc)是按成績這一列排序,加了desc關鍵詞表示降序排列。
通過下圖,我們就可以理解partiition by(分組)和order by(在組內排序)的作用了。
窗口函數具備了我們之前學過的group by子句分組的功能和order by子句排序的功能。那么,為什么還要用窗口函數呢?
這是因為,group by分組匯總后改變了表的行數,一行只有一個類別。而partiition by和rank函數不會減少原表中的行數。例如下面統計每個班級的人數。
那么為什么叫“窗口”函數呢?這是因為partition by分組后的結果稱為“窗口”,這里的窗口不是我們家里的門窗,而是表示“范圍”的意思。
簡單來說,窗口函數有以下功能:
1)同時具有分組和排序的功能
2)不減少原表的行數
3)語法如下:
?窗口函數?三.其他窗口函數
專用窗口函數rank, dense_rank, row_number有什么區別呢?
舉個例子,就能清楚了
select從上面的結果可以看出:
- rank函數:這個例子中是5位,5位,5位,8位,也就是如果有并列名次的行,會占用下一名次的位置。
- dense_rank函數:這個例子中是5位,5位,5位,6位,也就是如果有并列名次的行,不占用下一名次的位置。
- row_number函數:這個例子中是5位,6位,7位,8位,也就是不考慮并列名次的情況。
最后,需要強調的一點是:在上述的這三個專用窗口函數中,函數后面的括號不需要任何參數,保持()空著就可以。
【topN問題】
每組最大的N條記錄
現有“成績表”,記錄了每個學生各科的成績。表內容如下。問題:查找每個學生成績最高的2個科目
【解題思路】
【解體步驟】
步驟一:按姓名分組(partiotion by 姓名)、并按成績降序排列(order by 成績 desc),套入窗口函數的語法
select運行結果如下
步驟二:如上表黃色框內的數據,每個同學成績最好的2個科目,就是要求的解。
那么一下就會想到只要提取出“ranking”值小于等于2的數據就可以了。因此,只需要在上一步的slq語句里加入條件字句where就可以了,注意這樣是錯誤的!!!
一定要注意命令的運行順序,運行到”where ranking ? 2”的時候,因為select字句還沒有被執行,因此select中的“ranking”列還沒有出現,從而導致報錯。
因此,在這里用子查詢,也就是把第一步得到查詢結果作為一個新的表,sql語句如下:
select得到結果:
【如何在每個組里比較?】
還用上個例子中的表,查找單科成績高于該科目平均成績的學生名單?
【解題思路】
【解題步驟】
第1步,聚合函數avg()作為窗口函數,將每一科目成績的平均值求出。sql語句如下:
select結果如下
第2步,如上表,按科目分組后各科目的平均分已經計算出,那么,是不是只需要在上一步的slq語句里加入條件字句where就可以了?這里再次注意命令的執行順序!
和上個例子一樣用子查詢,也就是把第一步得到查詢結果作為一個新的表,sql語句如下:
select運行結果如下:
四.聚合函數
聚和窗口函數和上面提到的專用窗口函數用法完全相同,只需要把聚合函數寫在窗口函數的位置即可,但是函數后面括號里面不能為空,需要指定聚合的列名。
以下面的命令為例
select我單獨用sum運算過程進行說明:
如上圖,聚合函數sum在窗口函數中,是對自身記錄、及位于自身記錄以上的數據進行求和的結果。比如0004號,在使用sum窗口函數后的結果,是對0001,0002,0003,0004號的成績求和,若是0005號,則結果是0001號~0005號成績的求和,以此類推。
不僅是sum求和,平均、計數、最大最小值,也是同理,都是針對自身記錄、以及自身記錄之上的所有數據進行計算。
如果想要知道所有人成績的總和、平均等聚合結果,看最后一行即可。
這樣使用窗口函數有什么用呢?
聚合函數作為窗口函數,可以在每一行的數據里直觀的看到,截止到本行數據,統計數據是多少(最大值、最小值等)。同時可以看出每一行數據,對整體統計數據的影響。
五.窗口函數的移動平均
這里我們直接用聚合函數avg的窗口函數舉例說明:
selectrows和preceding這兩個關鍵字,是“之前~行”的意思。上面的句子中,是之前2行。也就是得到的結果是自身記錄及前2行的平均。
例如:學號0004學生的current_avg,是自己和前2位同學的平均,即0002,0003,0004三位同學成績的平均,其他數據的情況也一樣,下圖非常直觀的可以看到計算過程:
每一行得到的結果,都是當前行和前面2行的平均(共3行)。想要計算當前行與前n行(共n+1行)的平均時,只要調整rows…preceding中間的數字即可。
這里需要注意:在移動平均中,被選出的數據構成一個“框架”,例如,剛才例子中的0002、0003、0004行數據,就是一個“框架”。
這樣使用窗口函數有什么用呢?
由于這里可以通過preceding關鍵字調整作用范圍,在以下場景中非常適用:
在公司業績名單排名中,可以通過移動平均,直觀地查看到與相鄰名次業績的平均、求和等統計數據。六.總結
總結
以上是生活随笔為你收集整理的sql server累计求和函数_SQL基础--SQL高级功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信聊天记录转移
- 下一篇: inner join on 加条件和wh