窗口函數(開窗函數)及OVER子句(3):OVER子句完整語法及各選項詳解

窗口函數(開窗函數)及OVER子句(3):OVER子句完整語法及各選項詳解

若覺得本文寫得還可以,請多多關注本人所作書籍《C++語法詳解》電子工業出版社出版,作者 黃勇,網盤地址:
https://pan.baidu.com/s/1dIxLMN5b91zpJN2sZv1MNg

本文爲原創文章,轉載請註明出處,或註明轉載自“黃邦勇帥(原名:黃勇)

四、OVER子句完整語法
OVER子句完整語法如下:
在這裏插入圖片描述
爲避免混淆,本小節會把分區子句稱爲PARTITION BY從屬子句,排序子句稱爲ORDER BY從屬子句

分區子句< PARTITION BY clause >
1、所有窗口函數都支持分區子句。
2、分區子句用於對查詢結果集進行分區,其規則爲:只有在結果集的分區列中與當前行的分區列有相同值的行才進入分區,其餘行被過濾掉,若未指定PARTITION BY子句,則表示未分區,此時默認分區爲整個查詢結果集,若未指定框架子句,則由分區子句劃分的分區就是最終定義的窗口。比如PARTITION BY a,若當前行列a的值爲1,則只有查詢結果集中所有列a的值爲1的行才進入分區,其餘行被過濾掉。該子句的示例在前文已講解過,此處不再重述。

排序子句< ORDER BY clause >
1、所有窗口函數都支持排序子句,注意:SQL Server2012之後纔開始在聚合窗口函數中支持ORDER BY從屬子句。
2、ORDER BY從屬子句用於定義在窗口內的順序,不同類型的窗口函數,ORDER BY從屬子句的意義會有一些不相同,具體規則詳見對相應窗口函數的講解,另外,排序子句還會幫助框架子句對窗口進行進一步的限定或過濾
3、窗口函數的排序規範與顯示(或輸出)時的排序規範不同,窗口函數的排序子句,隻影響窗口內的數據,若指定了顯示排序,則最後輸出的排序以顯示排序爲準,而不是以窗口函數的排序爲準,若需要按一定順序顯示,則需要指定顯示排序。顯示排序指的是SELECT語句中的ORDER BY子句,比如SELECT * FROM T ORDER BY a,其中的ORDER BY就是顯示排序
4、窗口函數、NEXT VALUE FOR 函數不支持將整數索引作爲 ORDER BY 子句表達式。但可以使用子查詢返回一個常量作爲排序子句的元素,比如ORDER BY (SELECT 3)就是正確的,同理ORDER BY (select a from T4 where a=1),若子查詢返回的值是唯一的,也是正確的

框架子句< ROW or RANGE clause >
1、框架子句適用於聚合窗口函數和3個偏移函數(FIRSST_VALUE、LAST_VALUE、NTH_VALUE),注意:排名函數不支持框架子句。
2、框架子句是在一個分區內對行的進一步限制或過濾。也就是說,PARTITION BY從屬子句是對窗口的第一次過濾,框架子句是在第一次過濾的基礎上進行的第二次過濾,由框架子句過濾後的窗口,將成爲最終的窗口。
3、框架子句過濾窗口的基本規則是:基於排序子句的順序,在當前行所在分區中定義兩個點,在這兩點之間能形成框架的行纔會進入窗口,其餘行被再次過濾掉。
4、SQL Server使用ROWS或RANGE選項來定義框架的開始行和結束行,這兩個選項的基本規則如下:
 ROWS選項使用相對於當前行的偏移行數來定義框架的起點和終點。
 RANGE選項可以使用框架起/終點的值與當前行的值的差異來定義偏移的行數,SQL Server2017只實現了該選項的部分功能。因此本文主要對ROWS選項進行講解,在SQL Server中,RANGE與ROWS的原理是類似的,但是排序子句會對RANGE有影響,詳見後文
 ROWS/RANGE選項各參數的意義,可參閱語法的註釋,現在應該容易理解了
5、框架子句過濾分區的基本規則
1)、當使用< window frame preceding > 子句定義框架區域時,該子句中的參數只能用於指定窗口的起點,窗口的終點此時爲CURRENT ROW(即當前行),比如ROWS 2 PRECEDING與ROWS BETWEEN 2 PRECEDING AND CURRENT ROW相同,表示窗口總共有3行,包括當前行的前2行和當前行,假設當前行爲第5行且當前行所在分區足夠大,則該行的窗口爲第3,4,5行
2)、注意:不能只使用< window frame following > 子句定義框架區域,比如ROWS 2 FOLLOWING是錯誤的語句。
3)、當< 整數值> FOLLOWING 指定爲窗口起點時,終點不能是< 整數值> PRECEDING 或CURRENT ROW,比如,ROWS BETWEEN 1 FOLLOWING AND CURRENT ROW,或ROWS BETWEEN 1 FOLLOWING AND 1 PRECEDING都是錯誤的,
4)、RANGE 不能用於 < 整數值> PRECEDING 或 < 整數值> FOLLOWING。也就是說,使用RANGE時不能使用數值指定行數
5)、下面列舉幾個示例
在這裏插入圖片描述
6、RANGE選項定義框架的原理
RANGE選項定義的窗口除按照ROWS規則確定的行外,還包含ORDER BY從屬子句列表中列的值與當前行相應列具有相同值的所有行,這主要影響當使用CURRENT ROW確定窗口的起點或終點時。比如表有(a, b, c, d)四列,假設有(5, 2, 8, 9),(5, 6, 1, 2),(5, 6, 3, 4)三行,有語句

PARTITION BY a ORDER BY a, b RANGE UNBOUNDED PRECEDING

那麼,行(5, 6, 1, 2)的窗口爲(5, 2, 8, 9),(5, 6, 1, 2),(5, 6, 3, 4)三行。按照ROWS規則確定的行有(5, 2, 8, 9)、(5, 6, 1, 2),另外,還包含(a, b)列的值爲(5, 6)的行(5, 6, 3, 4),若把RANGE修改爲ROWS,則當前行(5, 6, 1, 2)的窗口只有(5, 2, 8, 9),(5, 6, 1, 2)兩行。
7、ORDER BY從屬子句對框架子句的影響
在這裏插入圖片描述

示例5.3:ROWS定義框架的原理(輸出結果見圖5.3)
select *,sum(c)over(partition by a order by a,b,c ROWS 2 PRECEDING ) as 框架1
		,sum(c)over(partition by a order by a,b,c ROWS UNBOUNDED PRECEDING) as 框架2
,sum(c)over(partition by a order by a,b,c
ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING) as 框架3	
		from T4 order by a,b,c;	--與框架子句排序一致,以免輸出時順序不一致

在這裏插入圖片描述
在這裏插入圖片描述

示例5.4:RANGE定義框架的原理(輸出結果見圖5.4)
select *,sum(c)over(partition by a order by a,b ROWS CURRENT ROW ) as 框架1
		,sum(c)over(partition by a order by a,b RANGE CURRENT ROW) as 框架2
		,sum(c)over(partition by a order by a,b ROWS UNBOUNDED PRECEDING) as 框架3
		,sum(c)over(partition by a order by a,b RANGE UNBOUNDED PRECEDING) as 框架4
		,sum(c)over(partition by a order by a,b) as 框架5	--框架5與框架4相同
		,sum(c)over(order by a,b RANGE UNBOUNDED PRECEDING) as 框架6  --注意該框架
		from T4 order by a,b;

在這裏插入圖片描述
示例說明:
1、框架1的過濾條件爲ROWS CURRENT ROW,因此窗口只有當前行一行,對窗口內c列進行求和,就是該行c列的值
2、框架2的過濾條件爲RANGE CURRENT ROW,表示窗口包含ORDER BY從屬子句列表中列的值與當前行相應列具有相同值的所有行,因此,行(5, 6, 11, 12)的窗口爲(a, b)列的值爲(5, 6)的所有行,即窗口爲(5, 6, 11, 12)、(5, 6, 3, 1)、(5, 6, 5, 4),對該窗口內的c列進行求和,其結果爲19(即11+3+5),從這裏可以明顯看到RANGE與ROWS的區別。行(5, 6, 3, 1)、(5, 6, 5, 4)的原理與行(5, 6, 11, 12)相同,其餘行的窗口都僅爲當前行一行。
3、框架3的過濾條件爲ROWS UNBOUNDED ROW,其窗口爲所在分區的開頭直至當前行,具體從略,詳見正文及上一示例的講解
4、框架4的過濾條件爲RANGE UNBOUNDED ROW,表示窗口除包含按照ROWS規則確定的行外,還包含ORDER BY從屬子句列表中列的值與當前行相應列具有相同值的所有行,因此,行(5, 6, 11, 12)的窗口爲,按照ROWS規則確定的行(5, 1, 2, 3)、(5, 6, 11, 12),還包含(a, b)列的值爲(5, 6)的行(5, 6, 3, 1)、(5, 6, 5, 4),對窗口內的c列進行求和,其結果爲21(即2+11+3+5)。行(5, 6, 3, 1)、(5, 6, 5, 4)的原理與行(5, 6, 11, 12)相同,(5, 9, 10, 11)、(5, 11, 22, 33)、(4, 10, 1, 8)的窗口爲所在分區的開頭直至當前行,除此之外的其餘行的窗口都僅爲當前行一行。
5、框架5與框架4是相同的,從略
6、框架6沒有PARTITION BY子句,因此,框架6的當前行所在的分區將是整個查詢結果集,RANGE UNBOUNDED ROW將在整個查詢結果集的基礎上進行過濾,比如,行(4, 10, 1, 8),因整個查詢結果集爲該行所在分區,所以,其窗口爲該行所在分區的開頭直至當前行,即窗口爲(1, 2, 3, 4)、(2, 3, 4, 5)、(4, 1, 2, 3)、(4, 10, 1, 8),對窗口內的c列進行求和,其結果爲10(即3+4+2+1);行(5, 6, 11, 12)的窗口共有8行,即(1, 2, 3, 4)到(5, 6, 5, 4)之間的所有行(含起點和終點),對窗口內的c列進行求和,其結果爲31(即3+4+2+1+2+11+3+5)

作者:黃邦勇帥(原名:黃勇)

在這裏插入圖片描述

主要參考文獻:
1、C++語法詳解 黃勇 編著 電子工業出版社 2017年7月
2、SQL Server 2012 T-SQL基礎教程 [美] Itzik Ben-Gan著 張洪舉 李聯國 張昊天 譯 人民郵電出版社 2013年12月
3、T-SQL性能調優祕笈------基於SQL Server 2012窗口函數 [美] Itzik Ben-Gan著 林德玲 方鑫譯 人民郵電出版社 2014年8月
4、SQL Server 2005技術內幕:T-SQL查詢 [美] Itzik Ben-Gan , Lubor Kollar , Dejan Sarka著 趙立東 唐燦 劉波 譯 趙立東 審校 電子工業出版社 出版日期不詳
4、SQL Server 2005技術內幕:T-SQL程序設計 [美] Itzik Ben-Gan , Dejan Sarka , Roger Wolter著 趙立東 譯 電子工業出版社 出版日期不詳
5、Microsoft SQL Server 2008技術內幕:T-SQL語言基礎 [美] Itzik Ben-Gan著 成保棟 張昱 譯 電子工業出版社 2009年10月
6、Microsoft SQL Server 2008技術內幕:T-SQL查詢 [美] Itzik Ben-Gan , Lubor Kollar , Dejan Sarka , Steve Kass著 成保棟 李保強 譯 電子工業出版社 2010年9月

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章