窗口函数本身不画图,但能生成平滑所需的数据序列——关键在于用AVG()配合ROWS BETWEEN构建滑动窗口,再将结果输入图表工具;普通AVG(sales)是全量聚合,只返回一行,而折线图需每行原始记录对应一个平滑值,必须通过OVER(ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)为每行计算局部平均。

直接说结论:窗口函数本身不画图,但能生成平滑所需的数据序列——关键在于用 AVG() 或 SUM() 配合 ROWS BETWEEN 构建滑动窗口,再把结果喂给图表工具(如 SSRS、Power BI 或前端 ECharts)。
为什么不能直接用 AVG() 而要加 ROWS BETWEEN
普通 AVG(sales) 是全量聚合,只返回一行;折线图需要每条原始记录都对应一个平滑值。必须靠 OVER(ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) 这类帧定义,让每一行都计算“截至当前、往前含2天”的平均值。
- 不写
ROWS BETWEEN:默认是UNBOUNDED PRECEDING AND CURRENT ROW,即从起点累加,适合累计曲线,不适合局部平滑 - 写成
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING:中心对称窗口,更接近“3点移动平均”,抗噪性更好 - SQL Server 2012+ 才完整支持
ROWS帧;2008 R2 及更早版本只能退化为自连接模拟,性能差且易出错
如何避免日期断档导致的平滑失真
真实销售数据常有缺日(比如周末无交易),若直接 ORDER BY sale_date,缺日会导致窗口跨度过大——例如周五后直接跳到周一,ROWS BETWEEN 2 PRECEDING AND CURRENT ROW 实际取到的是周三、周四、周一,中间空了两天,平滑值就失真。
- 先用 CTE 补齐日期:用
master..spt_values或递归CTE生成连续日期序列,再LEFT JOIN销售表,空值补 0 - 排序字段改用补全后的日期列,确保物理顺序与时间顺序严格一致
- 慎用
RANGE BETWEEN:它按值而非行数切窗,遇到重复日期(如多笔同日订单)会意外扩大窗口,优先选ROWS
SSRS 折线图里怎么接窗口函数结果
SSRS 不识别窗口函数语义,你得在数据集查询里完成全部计算,把平滑值作为普通列返回:
SELECT
d.fulldate AS [Date],
ISNULL(s.sales, 0) AS [RawSales],
AVG(ISNULL(s.sales, 0)) OVER (
ORDER BY d.fulldate
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS [SmoothedSales]
FROM dim_date d
LEFT JOIN store_sales s ON d.fulldate = s.sale_date
WHERE d.fulldate >= '2026-01-01'
- 图表的“值”字段绑
[SmoothedSales],不是原始[RawSales] - 类别组绑
[Date],必须是 datetime 类型,不能是字符串格式的日期 - 如果想叠加原始线和光滑线,就在同一个图表中添加第二个值系列,绑定
[RawSales]并设为虚线样式
真正容易被忽略的点是:窗口函数的排序必须严格单调——同一 ORDER BY 值出现多次时(比如多笔同秒订单),ROW_NUMBER() 会强制拆序,但 AVG() OVER(...ROWS...) 可能因 SQL Server 的行序不确定性导致相邻调用结果不一致;稳妥做法是追加唯一键(如 ORDER BY sale_date, id)锚定顺序。

















