从SQL Server 2005起,SQL Server开始支持窗口函数 (Window Function),以及到SQL Server 2012,窗口函数功能增强,目前为止支持以下几种窗口函数:
1. 排序函数 (Ranking Function) ;
2. 聚合函数 (Aggregate Function) ;
3. 分析函数 (Analytic Function) ;
4. NEXT VALUE FOR Function, 这是给sequence专用的一个函数;
一. 排序函数(Ranking Function)
帮助文档里的代码示例很全。
排序函数中,ROW_NUMBER()较为常用,可用于去重、分页、分组中选择数据,生成数字辅助表等等;
排序函数在语法上要求OVER子句里必须含ORDER BY,否则语法不通过,对于不想排序的场景可以这样变通;
drop table if exists test_ranking create table test_ranking ( id int not null, name varchar(20) not null, value int not null ) insert test_ranking select 1,'name1',1 union all select 1,'name2',2 union all select 2,'name3',2 union all select 3,'name4',2 select id , name, ROW_NUMBER() over (PARTITION by id ORDER BY name) as num from test_ranking select id , name, ROW_NUMBER() over (PARTITION by id) as num from test_ranking /* Msg 4112, Level 15, State 1, Line 1 The function 'ROW_NUMBER' must have an OVER clause with ORDER BY. */ --ORDERY BY后面给一个和原表无关的派生列 select id , name, ROW_NUMBER() over (PARTITION by id ORDER BY GETDATE()) as num from test_ranking select id , name, ROW_NUMBER() over (PARTITION by id ORDER BY (select 0)) as num from test_ranking
二. 聚合函数 (Aggregate Function)
SQL Server 2005中,窗口聚合函数仅支持PARTITION BY,也就是说仅能对分组的数据整体做聚合运算;
SQL Server 2012开始,窗口聚合函数支持ORDER BY,以及ROWS/RAGNE选项,原本需要子查询来实现的需求,如: 移动平均 (moving averages), 总计聚合 (cumulative aggregates), 累计求和 (running totals) 等,变得更加方便;
代码示例1:总计/小计/累计求和
drop table if exists test_aggregate; create table test_aggregate ( event_id varchar(100), rk int, price int ) insert into test_aggregate values ('a',1,10), ('a',2,10), ('a',3,50), ('b',1,10), ('b',2,20), ('b',3,30) --1. 没有窗口函数时,用子查询 select a.event_id, a.rk, --build ranking column if needed a.price, (select sum(price) from test_aggregate b where b.event_id = a.event_id and b.rk <= a.rk) as totalprice from test_aggregate a --2. 从SQL Server 2012起,用窗口函数 --2.1 --没有PARTITION BY, 没有ORDER BY,为全部总计; --只有PARTITION BY, 没有ORDER BY,为分组小计; --只有ORDER BY,没有PARTITION BY,为全部累计求和(RANGE选项,见2.2) select *, sum(price) over() as TotalPrice, sum(price) over(partition by event_id) as SubTotalPrice, sum(price) over(order by rk) as RunningTotalPrice from test_aggregate a --2.2 注意ORDER BY列的选择,可能会带来不同结果 select *, 郑州做人流哪里好:http://www.zzyyrl.com/郑州无痛人流去哪好:http://www.zzyyrl.com/郑州专业妇科医院:http://www.qudouwy.com/郑州哪家看妇科好:http://www.qudouwy.com/郑州妇科医院:http://www.qudouwy.com/郑州人流医院:http://www.sgrl029.com/郑州无痛人流哪家好:http://www.sgrl029.com/郑州人流手术医院:http://www.sgrl029.com/郑州同济医院:http://www.zztongjifk.com/ sum(price) over(partition by event_id order by rk) as totalprice from test_aggregate a /* event_id rk price totalprice a 1 10 10 a 2 10 20 a 3 50 70 b 1 10 10 b 2 20 30 b 3 30 60 */ select *, sum(price) over(partition by event_id order by price) as totalprice from test_aggregate a /* event_id rk price totalprice a 1 10 20 a 2 10 20 a 3 50 70 b 1 10 10 b 2 20 30 b 3 30 60 */ --因为ORDER BY还有个子选项ROWS/RANGE,不指定的情况下默认为RANGE UNBOUNDED PRECEDING AND CURRENT ROW --RANGE按照ORDER BY中的列值,将相同的值的行均视为当前同一行 select *,sum(price) over(partition by event_id order by price) as totalprice from test_aggregate a select *,sum(price) over(partition by event_id order by price range between unbounded preceding and current row) as totalprice from test_aggregate a --如果ORDER BY中的列值有重复值,手动改用ROWS选项即可实现逐行累计求和 select *,sum(price) over(partition by event_id order by price rows between unbounded preceding and current row) as totalprice from test_aggregate a