SQLServer2022新特性Window子句的使用
參考官方文檔
https://learn.microsoft.com/zh-cn/sql/t-sql/queries/select-window-transact-sql?view=sql-server-ver16
1、本文內(nèi)容
- 語法
- 參數(shù)
- 一般備注
- 示例
1.1、新特性適用于:
- SQL Server 2022 (16.x)
- Azure SQL 數(shù)據(jù)庫
- Azure SQL 托管實(shí)例
在應(yīng)用 OVER 子句中使用窗口的窗口函數(shù)之前,WINDOW 子句中的命名窗口定義確定行集的分區(qū)和排序。
1.2、備注
WINDOW 子句要求數(shù)據(jù)庫兼容性級(jí)別為 160 或更高。 如果數(shù)據(jù)庫兼容性級(jí)別低于 160,則 SQL Server 無法使用 WINDOW 子句執(zhí)行查詢。
可在 sys.databases 視圖或數(shù)據(jù)庫屬性中查看兼容性級(jí)別。 可以使用以下命令更改數(shù)據(jù)庫的兼容級(jí)別:
ALTER DATABASE DatabaseName SET COMPATIBILITY_LEVEL = 160
2、語法
WINDOW window_name AS ( [ reference_window_name ] [ <PARTITION BY clause> ] [ <ORDER BY clause> ] [ <ROW or RANGE clause> ] ) <PARTITION BY clause> ::= PARTITION BY value_expression , ... [ n ] <ORDER BY clause> ::= ORDER BY order_by_expression [ COLLATE collation_name ] [ ASC | DESC ] [ ,...n ] <ROW or RANGE clause> ::= { ROWS | RANGE } <window frame extent>
3、參數(shù)
window_name
定義的窗口規(guī)范的名稱。 OVER 子句中的窗口函數(shù)將使用此名稱來引用窗口規(guī)范。 窗口名稱必須符合標(biāo)識(shí)符的規(guī)則。
reference_window_name
當(dāng)前窗口引用的窗口的名稱。 引用的窗口必須位于 WINDOW 子句中定義的窗口之間。
其他參數(shù)包括:
PARTITION BY:將查詢結(jié)果集分為多個(gè)分區(qū)。
ORDER BY:定義結(jié)果集的每個(gè)分區(qū)中行的邏輯順序。
ROWS/RANGE:通過指定分區(qū)中的起點(diǎn)和終點(diǎn)來限制分區(qū)中的行數(shù)。
有關(guān)參數(shù)的更多具體詳細(xì)信息,請(qǐng)參閱 OVER 子句
https://learn.microsoft.com/zh-cn/sql/t-sql/queries/select-over-clause-transact-sql?view=sql-server-ver16
4、一般備注
可在 WINDOW 子句中定義多個(gè)命名窗口。
通過使用后跟附加規(guī)范的 window_name,可將附加組件添加到 OVER 子句中的命名窗口。 但是,不能在 OVER 子句中重新定義 WINDOW 子句中指定的屬性。
當(dāng)查詢使用多個(gè)窗口時(shí),一個(gè)命名窗口可以使用 window_name 引用另一個(gè)命名窗口。 在這種情況下,必須在引用窗口的窗口定義中指定引用 window_name。 一個(gè)窗口中定義的窗口組件不能由另一個(gè)引用它的窗口重新定義。
根據(jù)在 window 子句中定義窗口的順序,允許向前和向后的窗口引用。 換句話說,一個(gè)窗口可使用在它所屬的 <window_expression> 中定義的任何其他窗口作為 reference_window_name,而不管它們的定義順序如何。 不允許循環(huán)引用和在單個(gè)窗口中使用多個(gè)窗口引用。
<window_expression> 中包含的已定義窗口的新 window_name 的范圍由屬于 <window_expression> 的任何窗口定義,以及包含該 window 子句的 <query_specification> 或 的 SELECT 子句組成。 如果 <window_expression> 包含在屬于簡(jiǎn)單表查詢 <query_expression> 的 <query_specification> 中,則新 window_name 的范圍還包括該 <query_expression> 的 <order_by_expression>(如果有)。
OVER 子句中窗口規(guī)范與基于語義的聚合函數(shù)和分析函數(shù)的使用限制適用于 WINDOW 子句。
5、示例
5.1、 指定在 window 子句中定義的窗口
測(cè)試表及數(shù)據(jù)準(zhǔn)備
create table t_order_sales( order_id varchar(4) primary key, user_no varchar(8), amount int, create_date datetime ); insert into t_order_sales values ('1001','C0001',1920,'2020-01-01'); insert into t_order_sales values ('1002','C0002',3510,'2019-03-02'); insert into t_order_sales values ('1003','C0003',3500,'2022-04-12'); insert into t_order_sales values ('1004','C0004',8030,'2021-05-10'); insert into t_order_sales values ('1005','C0011',9600,'2023-03-12'); insert into t_order_sales values ('1006','C0002',5021,'2022-01-05'); insert into t_order_sales values ('1007','C1002',6160,'2018-01-06'); insert into t_order_sales values ('1008','C2007',3201,'2024-01-10'); insert into t_order_sales values ('1009','C3008',8760,'2023-01-16'); insert into t_order_sales values ('1010','V0002',8870,'2021-01-22'); SELECT * FROM dbo.t_order_sales; order_id user_no amount create_date -------- -------- ----------- ----------------------- 1001 C0001 1920 2020-01-01 00:00:00.000 1002 C0002 3510 2019-03-02 00:00:00.000 1003 C0003 3500 2022-04-12 00:00:00.000 1004 C0004 8030 2021-05-10 00:00:00.000 1005 C0011 9600 2023-03-12 00:00:00.000 1006 C0002 5021 2022-01-05 00:00:00.000 1007 C1002 6160 2018-01-06 00:00:00.000 1008 C2007 3201 2024-01-10 00:00:00.000 1009 C3008 8760 2023-01-16 00:00:00.000 1010 V0002 8870 2021-01-22 00:00:00.000
指定在 window 子句中定義的窗口
SELECT ROW_NUMBER() OVER win AS "Row Number", order_id,user_no,amount,create_date FROM t_order_sales WINDOW win AS (ORDER BY amount DESC) GO Row Number order_id user_no amount create_date -------------------- -------- -------- ----------- ----------------------- 1 1005 C0011 9600 2023-03-12 00:00:00.000 2 1010 V0002 8870 2021-01-22 00:00:00.000 3 1009 C3008 8760 2023-01-16 00:00:00.000 4 1004 C0004 8030 2021-05-10 00:00:00.000 5 1007 C1002 6160 2018-01-06 00:00:00.000 6 1006 C0002 5021 2022-01-05 00:00:00.000 7 1002 C0002 3510 2019-03-02 00:00:00.000 8 1003 C0003 3500 2022-04-12 00:00:00.000 9 1008 C2007 3201 2024-01-10 00:00:00.000 10 1001 C0001 1920 2020-01-01 00:00:00.000 (10 行受影響)
以下查詢與上述查詢等效,但不使用 WINDOW 子句。
Row Number order_id user_no amount create_date -------------------- -------- -------- ----------- ----------------------- 1 1005 C0011 9600 2023-03-12 00:00:00.000 2 1010 V0002 8870 2021-01-22 00:00:00.000 3 1009 C3008 8760 2023-01-16 00:00:00.000 4 1004 C0004 8030 2021-05-10 00:00:00.000 5 1007 C1002 6160 2018-01-06 00:00:00.000 6 1006 C0002 5021 2022-01-05 00:00:00.000 7 1002 C0002 3510 2019-03-02 00:00:00.000 8 1003 C0003 3500 2022-04-12 00:00:00.000 9 1008 C2007 3201 2024-01-10 00:00:00.000 10 1001 C0001 1920 2020-01-01 00:00:00.000 (10 行受影響)
5.2、在多個(gè) over 子句中指定單個(gè)窗口
SELECT order_id,user_no,amount,create_date ,SUM(amount) OVER win AS Total ,AVG(amount) OVER win AS "Avg" ,COUNT(amount) OVER win AS "Count" ,MIN(amount) OVER win AS "Min" ,MAX(amount) OVER win AS "Max" FROM t_order_sales WHERE user_no IN ('C0002','V0002') WINDOW win AS (PARTITION BY user_no); GO order_id user_no amount Total Avg Count Min Max -------- -------- ----------- ----------- ----------- ----------- ----------- ----------- 1002 C0002 3510 8531 4265 2 3510 5021 1006 C0002 5021 8531 4265 2 3510 5021 1010 V0002 8870 8870 8870 1 8870 8870 (3 行受影響)
以下查詢與上述查詢等效,但不使用 WINDOW 子句。
SELECT order_id,user_no,amount ,SUM(amount) OVER (PARTITION BY user_no) AS Total ,AVG(amount) OVER (PARTITION BY user_no) AS "Avg" ,COUNT(amount) OVER (PARTITION BY user_no) AS "Count" ,MIN(amount) OVER (PARTITION BY user_no) AS "Min" ,MAX(amount) OVER (PARTITION BY user_no) AS "Max" FROM t_order_sales WHERE user_no IN ('C0002','V0002'); GO order_id user_no amount Total Avg Count Min Max -------- -------- ----------- ----------- ----------- ----------- ----------- ----------- 1002 C0002 3510 8531 4265 2 3510 5021 1006 C0002 5021 8531 4265 2 3510 5021 1010 V0002 8870 8870 8870 1 8870 8870 (3 行受影響)
5.3、在 window 子句中定義通用規(guī)范
SELECT order_id,user_no,amount, SUM(amount) OVER win AS Total, AVG(amount) OVER(win PARTITION BY user_no) AS Avg, COUNT(amount) OVER(win ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING) AS Count FROM t_order_sales WHERE user_no IN ('C0002','V0002') WINDOW win AS (ORDER BY user_no, create_date); GO order_id user_no amount Total Avg Count -------- -------- ----------- ----------- ----------- ----------- 1002 C0002 3510 3510 3510 2 1006 C0002 5021 8531 4265 3 1010 V0002 8870 17401 8870 3 (3 行受影響)
以下查詢與上述查詢等效,但不使用 WINDOW 子句。
SELECT order_id,user_no,amount, SUM(amount) OVER (ORDER BY user_no, create_date) AS Total, AVG(amount) OVER (PARTITION BY user_no ORDER BY user_no, create_date) AS Avg, COUNT(amount) OVER(ORDER BY user_no, create_date ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING) AS Count FROM t_order_sales WHERE user_no IN ('C0002','V0002'); GO
5.4、 向前和向后的窗口引用
此示例顯示在 WINDOW 子句中定義新窗口時(shí),將命名窗口用作前向引用和向后引用。
SELECT order_id,user_no,amount, SUM(amount) OVER win2 AS Total, AVG(amount) OVER win1 AS Avg FROM t_order_sales WHERE user_no IN ('C0002','V0002') WINDOW win1 AS (win3), win2 AS (ORDER BY user_no), win3 AS (win2 PARTITION BY user_no); GO order_id user_no amount Total Avg -------- -------- ----------- ----------- ----------- 1002 C0002 3510 8531 4265 1006 C0002 5021 8531 4265 1010 V0002 8870 17401 8870 (3 行受影響)
6、總結(jié)
Window 子句通常與 OVER() 子句相關(guān),它經(jīng)常與窗口函數(shù)(如 ROW_NUMBER(), RANK(), DENSE_RANK(), SUM(), AVG(), MIN(), MAX() 等函數(shù)的 OVER() 版本)一起使用。這些窗口函數(shù)允許你在結(jié)果集的每個(gè)行上執(zhí)行計(jì)算,這些計(jì)算會(huì)考慮與當(dāng)前行相關(guān)的其他行(例如,前面的幾個(gè)示例)
SQL Server 中與窗口函數(shù)相關(guān)的一般知識(shí)或最佳實(shí)踐,那么以下是一些要點(diǎn):
- 使用 OVER() 子句:通過為窗口函數(shù)指定 OVER() 子句,你可以定義窗口的邊界和排序順序。
- PARTITION BY:在 OVER() 子句中使用 PARTITION BY 可以將數(shù)據(jù)分成多個(gè)分區(qū),并為每個(gè)分區(qū)獨(dú)立地計(jì)算窗口函數(shù)。
- ORDER BY:在 OVER() 子句中使用 ORDER BY 可以定義窗口中行的順序。這對(duì)于需要基于行順序(如累積總和或運(yùn)行平均值)的計(jì)算特別有用。
- 常見的窗口函數(shù):包括 ROW_NUMBER(), RANK(), DENSE_RANK(), SUM() OVER(), AVG() OVER(), MIN() OVER(), MAX() OVER() 等。
- 性能考慮:窗口函數(shù)可能會(huì)對(duì)性能產(chǎn)生影響,特別是在處理大量數(shù)據(jù)時(shí)。確保你的查詢已針對(duì)性能進(jìn)行了優(yōu)化,并考慮使用索引、分區(qū)等策略來加速查詢。
- 兼容性:不同的數(shù)據(jù)庫系統(tǒng)對(duì)窗口函數(shù)的支持可能有所不同。在將使用窗口函數(shù)的查詢從一個(gè)系統(tǒng)遷移到另一個(gè)系統(tǒng)時(shí),請(qǐng)務(wù)必檢查目標(biāo)系統(tǒng)的兼容性。
到此這篇關(guān)于SQLServer2022新特性Window子句的文章就介紹到這了,更多相關(guān)SQL Window子句內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MySQL之使用WITH子句和臨時(shí)表達(dá)式進(jìn)行數(shù)據(jù)分析和篩選方式
- MySQL表的增刪查改及聚合函數(shù)/group?by子句的使用方法舉例
- SQL HAVING子句在GROUP BY中的條件篩選靈活運(yùn)用
- SQL?JOIN?子句合并多個(gè)表中相關(guān)行全面指南
- Mysql實(shí)現(xiàn)模糊查詢的兩種方式(like子句?、正則表達(dá)式)
- SQL中where子句與having子句的區(qū)別小結(jié)
- MySQL中Union子句不支持order by的解決方法
- 詳解MySQL中WHERE子句的用法
- MySQL中BETWEEN子句的用法詳解
相關(guān)文章
一個(gè)刪選數(shù)據(jù)的例子,使用GROUP、DISTINCT實(shí)例解析
今天遇到的問題,糾結(jié)了一上午,終于解決了。在此記錄下來,自我認(rèn)為還有很多類似的問題都可以套用這段代碼2013-09-09SQL語句中含有乘號(hào)報(bào)錯(cuò)的處理辦法
這篇文章主要介紹了SQL語句中含有乘號(hào)報(bào)錯(cuò)的處理辦法,需要的朋友可以參考下2014-08-08sqlserver 2000數(shù)據(jù)庫同步 同步兩個(gè)SQLServer數(shù)據(jù)庫的內(nèi)容
程序代碼可以有版本管理CVS進(jìn)行同步管理,可是數(shù)據(jù)庫同步就非常麻煩,只能自己改了一個(gè)后再去改另一個(gè),如果忘記了更改另一個(gè)經(jīng)常造成兩個(gè)數(shù)據(jù)庫的結(jié)構(gòu)或內(nèi)容上不一致.2010-05-05insert select與select into 的用法使用說明
將一個(gè)table1的數(shù)據(jù)的部分字段復(fù)制到table2中,或者將整個(gè)table1復(fù)制到table2中,這時(shí)候我們就要使用SELECT INTO 和 INSERT INTO SELECT 表復(fù)制語句了2011-12-12sql時(shí)間格式化輸出、Convert函數(shù)應(yīng)用示例
這篇文章主要介紹了sql時(shí)間格式化輸出、Convert函數(shù)應(yīng)用,需要的朋友可以參考下2014-03-03批量更新數(shù)據(jù)庫所有表中字段的內(nèi)容,中木馬后的急救處理
這里對(duì)非ntext,nvarchar,image字段有效,這些字段要?jiǎng)e外處理. 這下面的內(nèi)容,部分我是自己用過的.對(duì)于ntext等字段大于8000的我沒有試過.一起寫在這里2009-09-09win7系統(tǒng)安裝SQLServer2000的詳細(xì)步驟(圖文)
這篇文章主要介紹了win7系統(tǒng)安裝SQLServer2000的詳細(xì)步驟,里面有一些需要注意的事項(xiàng),大家可以參考下2014-07-07