1、窗口函數入門
(1)窗口函數的作用於由over子句定義的數據行集合
(2)窗口函數主要用於分析目的、匯總計算、移動平均值計算、計算數據差、發現數據島等
(3)這些函數都是基於標准sql(ISO 和 ANSI 標准)
(4)其概念的精髓在於可以通過對數據行集合或數據行窗口進行多種計算,最后得到單個值
(5)窗口函數讓我們以更加輕松、直觀、高效的方式解決數據行集合計算和分析問題
(6)窗口函數是SQL 查詢的未來方向,值得學習
2、排名窗口的背景
2.1窗口函數的描述
(1)窗口函數作用於一個數據行集合。窗口是標准sql術語,用來描述sql語句中用over子句划定的內容,這個內容就是窗口函數的作用域
(2)對於結果集的每一行,Over子句都定義一個與之對應的獨立窗口
-- 使用rank函數、更具val降序排序,並輸出排名 SELECT orderid, orderdate, val, RANK() OVER(ORDER BY val DESC) AS rnk FROM Sales.OrderValues ORDER BY rnk;
(3)標准SQL第一次支持窗口函數是在SQL:1999的拓展文檔,此時稱為“OLAP”,最新的SQL 標准中已經有了非常豐富和全面的窗口函數了
(4)標准SQL支持幾種窗口函數類型: 集合、排序 、分布、 偏移
(5)聚集窗口函數就是常用的Sum、Count 、Min 、Max 等函數,一個聚集函數的作用域就是一個記錄集 、這個記錄集由查詢分組、或窗口描述來定義
(6)排名函數有rank 、dense_rank、 row_number、 ntile ,SQL 標准中將前兩個和后兩個歸於不同類型
(7)分布函數有percent_rank、cume_dist、percentile_count 、percentile_disc ,這四個函數從sql server 2012 開始引入
(8)窗口函數的具體應用: 分頁、去重、返回前n條數據、計算累積合計、對時間間隔進行操作、統計最大並發會話數、找出數據差距(gap)、找數據島(island)、計算百分比、計算分布模式、排序層次結構、數據透視、計算時效性、計算近因
3、窗口函數中的元素
窗口函數的行為描述出現在Over子句中,涉及3個元素、分區、排序、框架
3.1 分區(partition by)
(1)分區元素使得將我們的窗口范圍限制為只與當前行的分區特性(分區列)值相等的行集
(2)理解分區,要理解分區的過濾、賽選 窗口行集
3.2排序
(1)排序元素定義計算的順序,且定義的是分區內的順序
(2)sql server 對聚合函數中排序的支持是從sqlserver2012開始的
3.3框架
(1) 從本質上來說,框架是一個在分區內對行進一步限制的賽選器
(2) 框架是在窗口使用partition 過濾,然后使用order by 排序之后,進一步限制范圍
(3)sql server 2012開始支持框架
(4)框架限制格式略,其實是指定上下界,上下界通過當前行的偏移量來指定
4、支持窗口函數的查詢元素
並不是所有的查詢子句都支持窗口函數、只有select 和 orderby子句支持,這是為了避免二義性(“同時執行的原因,導致結果不確定”),把查詢結果(幾乎是)當成窗口的起點
5、聚合窗口函數
5.1聚合窗口函數描述
(1)窗口聚合函數和分組聚合函數的功能是相同的,一個聚合函數作用於一個行集上,使用什么語言機制來定義不重要
(2)在標准sql 中聚合窗口函數支持三種元素,分區、排序、框架,這三種元素的目的都是對窗口內的行進行過濾
(3)當不對窗口進行任何限制的時候,即over子句后面的括號為空,select 的結果集 直接 作為窗口函數的輸入
5.2聚合與分區
查看一個例子,體驗聚合函數作用的窗口使用與沒有使用分區過濾過濾的區別
-- default and explicit partitioning USE TSQL2012; SELECT orderid, custid, val, SUM(val) OVER() AS sumall, SUM(val) OVER(PARTITION BY custid) AS sumcust FROM Sales.OrderValues AS O1; /* orderid custid val sumall sumcust -------- ------- ------- ----------- -------- 10643 1 814.50 1265793.22 4273.00 10692 1 878.00 1265793.22 4273.00 10702 1 330.00 1265793.22 4273.00 10835 1 845.80 1265793.22 4273.00 10952 1 471.20 1265793.22 4273.00 11011 1 933.50 1265793.22 4273.00 10926 2 514.40 1265793.22 1402.95 10759 2 320.00 1265793.22 1402.95 10625 2 479.75 1265793.22 1402.95 10308 2 88.80 1265793.22 1402.95 ... */
6、排名窗口函數
6.1 row_number()
(1)row_number()根據over子句中order by 排序結果,分配連續遞增整數
(2)order by 排序元素值相等的兩列,即使值沒有增加,row_number()也增加、即row_number()必須生成唯一值、即使排序值有相等情況
6.2 rank()
(1) rank 是在分區范圍內比較排序值的大小,返回 大於或小於當前排序值的記錄個數+1
(2)根據上訴邏輯,當不同記錄擁有相同的邏輯排序值,那么rank 返回的排名值相等,這與row_number 相等
6.3dense_rank()
(1)dense_rank() 處理邏輯類似rank,都是比較值,取個數,因此當排序值相等,排名值也相等
(2)dense_rank 與rank 的區別是,在計算個數的時候,rank 不去重,dense_rank ,會去重
6.4ntile 函數
(1)ntile 函數允許將結果中的行與大小相等的行組關聯起來
(2)將分區分成多少個組,在函數輸入總指定,如ntile(10),分成10個組
(3)返回row_number排序,分組之后的組號
7、偏移開窗函數
這個就是找當前行偏移指定行的數的值,用的少
8、聚合開窗函數
(1)支撐 分區、 排序 、框架
(2)和普通聚合函數沒有區別,常規聚合作用了分組、開窗聚合聚合於窗口