SQL Server 2008 开窗函数

开窗函数的概念

SQL Server 2008引入了开窗函数(Window Functions),允许在查询结果集的子集(称为“窗口”)上执行计算,而无需分组或聚合整个结果集。开窗函数通过OVER()子句定义窗口的范围,支持对数据进行分区、排序和帧划分。

常见的开窗函数类型

聚合开窗函数
SUM()AVG()COUNT()等,可与OVER()结合使用,实现分区的聚合计算。

SELECT SalesOrderID, ProductID, LineTotal,  
       SUM(LineTotal) OVER(PARTITION BY SalesOrderID) AS OrderTotal  
FROM Sales.SalesOrderDetail;  

排名开窗函数
包括ROW_NUMBER()RANK()DENSE_RANK()NTILE(),用于生成分区内的排名值。

SELECT ProductID, Name, ListPrice,  
       RANK() OVER(ORDER BY ListPrice DESC) AS PriceRank  
FROM Production.Product;  

分析开窗函数
FIRST_VALUE()LAST_VALUE()LAG()LEAD(),用于访问窗口内其他行的数据。

SELECT BusinessEntityID, RateChangeDate, Rate,  
       LAG(Rate, 1, 0) OVER(ORDER BY RateChangeDate) AS PreviousRate  
FROM HumanResources.EmployeePayHistory;  

OVER()子句的组成部分

PARTITION BY
将数据划分为多个分区,函数在每个分区内独立计算。

SELECT CustomerID, SalesOrderID, TotalDue,  
       AVG(TotalDue) OVER(PARTITION BY CustomerID) AS AvgOrderByCustomer  
FROM Sales.SalesOrderHeader;  

ORDER BY
定义分区内数据的排序方式,影响排名函数和帧的范围。

SELECT ProductID, SalesOrderID, OrderQty,  
       SUM(OrderQty) OVER(PARTITION BY ProductID ORDER BY SalesOrderID) AS RunningTotal  
FROM Sales.SalesOrderDetail;  

ROWS/RANGE
指定帧的边界,如ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING

SELECT Date, SalesAmount,  
       AVG(SalesAmount) OVER(ORDER BY Date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS MovingAvg  
FROM Sales.DailySales;  

实际应用场景

计算移动平均
通过定义帧范围实现动态计算。

SELECT Month, Revenue,  
       AVG(Revenue) OVER(ORDER BY Month ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS MovingAvg  
FROM Sales.MonthlyRevenue;  

填充缺失数据
使用LAG()LEAD()引用相邻行的值。

SELECT Date, Temperature,  
       LAG(Temperature, 1) OVER(ORDER BY Date) AS PreviousDayTemp  
FROM Weather.Readings;  

生成连续排名
DENSE_RANK()避免排名值的间隔。

SELECT StudentID, Score,  
       DENSE_RANK() OVER(ORDER BY Score DESC) AS Rank  
FROM Exam.Results;  

性能注意事项

开窗函数可能增加查询复杂度,尤其在处理大数据集时。合理使用索引和限制分区范围可优化性能。避免在OVER()子句中使用不必要的排序或宽泛的帧定义。

开窗函数在SQL Server 2008中显著增强了数据分析能力,适用于复杂报表、趋势分析和数据比对场景。

PARTITION BY 的适用场景

PARTITION BY 用于窗口函数中,将数据分成多个分区(组),在每个分区内独立计算。适合需要对数据进行分组后分别聚合或分析的场景。

需要按照某一列或多列的值将数据分组时使用。例如计算每个部门的平均工资,可以按部门分区。每个分区会单独计算平均值,互不干扰。

需要对分组后的数据进行排名、累计求和等操作时使用。例如计算每个部门内员工的工资排名,需要先按部门分区,再在分区内排序计算排名。

ORDER BY 的适用场景

ORDER BY 用于对查询结果或窗口函数中的数据进行排序。适合需要明确排序规则的场景。

在普通查询中需要对最终结果排序时使用。例如查询员工信息并按工资从高到低显示。

在窗口函数中需要定义计算顺序时使用。例如计算累计和,需要先按日期排序再累加。排序决定了窗口函数计算的逻辑顺序。

PARTITION BY 和 ORDER BY 的组合使用

窗口函数中经常同时使用这两个子句。PARTITION BY 先分组,ORDER BY 再定义组内顺序。

计算移动平均时需要先按股票代码分区,再按交易日期排序。这样会在每支股票的时间序列上计算移动平均值。

计算部门内工资排名时需要先按部门分区,再按工资降序排序。这样能得到每个部门独立的工资排名。

关键区别

PARTITION BY 影响数据的分组方式,不改变每个分区内行的顺序。ORDER BY 只影响排序,不改变数据的分组。

PARTITION BY 后的窗口函数会对每个分区独立计算。只有 ORDER BY 时,窗口函数会跨所有数据计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ricky_Theseus

感谢大家,祝您生活愉快

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值