必须将兼容性级别设为160,否则sql server 2022不识别window关键字而报语法错误;需用select查当前级别,再用alter database升级,且不可逆;window子句须紧接from后、group by前,命名需避免冲突,仅复用窗口结构定义,不提升单次窗口函数性能。

必须把兼容性级别设为 160,否则 WINDOW 关键字直接报错,不是警告,是语法不识别。
如何确认并升级数据库兼容性级别
SQL Server 2022 的 WINDOW 子句只在兼容性级别 160 及以上生效。低于该级别时,解析器根本不会识别 WINDOW 这个词,直接抛出 Incorrect syntax near 'WINDOW'。
- 查当前级别:
SELECT compatibility_level FROM sys.databases WHERE name = 'YourDB' - 升级命令(不可逆):
ALTER DATABASE YourDB SET COMPATIBILITY_LEVEL = 160 - 升级后无法回退到 150 或更低——除非重建数据库
- 升级前建议做回归测试,旧版隐式类型转换规则可能有细微变化
WINDOW子句的正确位置和写法
WINDOW 不是函数也不是独立语句,它必须紧接在 FROM(含 JOIN、WHERE)之后、GROUP BY/HAVING/ORDER BY 之前。放错位置会直接语法报错。
- ✅ 正确顺序:
SELECT ..., ROW_NUMBER() OVER w FROM t WHERE ... WINDOW w AS (PARTITION BY x ORDER BY y) - ❌ 错误写法:
SELECT ..., ROW_NUMBER() OVER w FROM t WINDOW w AS (...) ORDER BY ...(WINDOW在ORDER BY后面) - ❌ 错误写法:
SELECT ..., ROW_NUMBER() OVER w FROM t WINDOW w AS (...) GROUP BY x(WINDOW在GROUP BY前面但被挡住) - 窗口名(如
w)不能和已有列名、表名冲突;PostgreSQL 会拒绝,SQL Server 虽不报但建议用带语义的名,比如w_dept_salary_desc
命名窗口能复用哪些内容,不能复用哪些
WINDOW 子句只复用窗口结构定义:即 PARTITION BY、ORDER BY 和 ROWS/RANGE 框架。它不包含函数本身,也不支持动态表达式或跨层级引用。
- ✅ 可复用:
PARTITION BY dept_id ORDER BY salary DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW - ❌ 不能写函数:
WINDOW w AS (AVG(salary) PARTITION BY ...)是非法的 - ❌ 不支持动态字段:
PARTITION BY @col或ORDER BY CASE WHEN ... END在WINDOW定义里不被允许 - ❌ 作用域仅限当前查询层级:CTE、子查询、外部查询各自定义的
WINDOW互不可见
为什么用了WINDOW子句还是没变快
性能提升只发生在“多个同构窗口函数共用同一定义”的场景下,且前提是优化器能省掉重复解析。它不解决排序慢、索引缺失、高基数分区等底层问题。
- 执行计划中,所有
OVER w最终都会被展开成等价的完整OVER (PARTITION BY ... ORDER BY ...),运行时行为和手写一模一样 - 真正卡性能的地方仍是
PARTITION BY和ORDER BY列是否建了合适索引——没索引照样排序溢出到tempdb - 如果只用一次窗口函数,硬写
OVER ()更清晰;强行套WINDOW w AS ()反而增加阅读成本 - 最容易被忽略的是:改完
WINDOW定义后,得立刻检查所有引用它的OVER w是否都在同一层查询里——嵌套深时,漏看一层就查不到定义










