WINDOW子句需兼容级别160,必须位于FROM后、GROUP BY前,仅支持PARTITION BY/ORDER BY/ROWS/RANGE,不跨查询层级,多窗口复用可降解析开销但不改变执行逻辑。

WINDOW子句必须搭配兼容性级别 160 才能用
SQL Server 解析器在低于 160 的兼容级别下根本不认识 WINDOW 关键字,直接报错:Incorrect syntax near 'WINDOW'。这不是警告,是语法解析失败。
必须显式升级数据库级别:
ALTER DATABASE YourDB SET COMPATIBILITY_LEVEL = 160
升级后无法回退到 150 或更低(除非重建数据库)。执行前建议先查当前级别:
SELECT compatibility_level FROM sys.databases WHERE name = 'YourDB'
- 升级后需回归测试——旧版隐式类型转换规则可能变化,尤其涉及
ORDER BY中表达式类型推导时 - Azure SQL 数据库和托管实例默认已启用 160,但本地部署的 SQL Server 2022 实例仍默认为 150
WINDOW子句的位置和语法不能错
WINDOW 必须紧接在 FROM(含 JOIN、WHERE)之后、GROUP BY/HAVING/ORDER BY 之前。写错位置会直接语法报错。
正确写法示例:
SELECT dept_id, salary, ROW_NUMBER() OVER w AS rn, AVG(salary) OVER w AS avg_sal FROM employee WHERE status = 'active' WINDOW w AS (PARTITION BY dept_id ORDER BY salary DESC)
- 窗口名
w不能和已有列名、表别名冲突(PostgreSQL 会拒绝,SQL Server 虽不报但易混淆) - 定义里不能包含函数或聚合,只允许
PARTITION BY、ORDER BY、ROWS/RANGE框架 - 不支持动态表达式,比如
PARTITION BY @col_name或ORDER BY CASE WHEN ...都非法
复用窗口定义只解决“写法重复”,不解决排序慢
WINDOW 子句的价值是编译期优化:SQL Server 只解析一次窗口结构,执行计划中只存一份元数据,降低 CPU 解析开销和内存占用。但它不会改变最终执行逻辑——所有 OVER w 在运行前都会被展开成等价的完整 OVER (PARTITION BY ... ORDER BY ...)。
- 如果
PARTITION BY dept_id ORDER BY salary DESC没有对应索引,照样触发大排序,溢出到tempdb - 性能收益集中在多窗口函数共用同一定义的场景(≥2 个),单次使用反而增加阅读成本
- 框架如
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW写在WINDOW定义里,所有引用自动同步,避免漏改
命名窗口作用域仅限当前查询层级
WINDOW 定义不会穿透 CTE、子查询或外部查询。你在主查询定义的 w,进不了 WITH t AS (SELECT ...) 里面;反过来,CTE 内定义的也不能被外层引用。
- 想跨层级复用?只能把共用逻辑提前到最外层 CTE 中预计算,或在每个层级单独写一遍
WINDOW w AS (...) - 不支持“继承式”定义,例如
WINDOW w2 AS (w1 ORDER BY other_col)在 SQL Server 中无效(PostgreSQL 支持,但 SQL Server 不认) - 多个命名窗口可并列定义:
WINDOW w1 AS (...), w2 AS (...),但彼此不能互相引用
WINDOW 块被塞到了 ORDER BY 后面、或者误以为加了它就不用管索引了。

















