oracle 21c 的 window、groups 和 exclude 三大特性协同提升窗口函数能力:window 支持复用窗口定义避免重复书写;groups 按排序组而非数值范围解决重复值歧义;exclude 精准排除当前行或同类行参与计算。

Oracle 21c 的窗口函数不是“升级版语法糖”,而是真正改变了写法逻辑和可维护性的能力增强——尤其当你需要复用相同窗口定义、处理重复值边界、或排除当前行干扰时,WINDOW、GROUPS 和 EXCLUDE 这三个特性缺一不可。
如何用 WINDOW 子句避免重复写 PARTITION BY
在 21c 之前,对同一分区做多个聚合就得反复写 PARTITION BY deptno,既冗长又易错。21c 允许把窗口定义抽出来重用:
- 写法必须是
WINDOW w1 AS (PARTITION BY deptno),放在FROM子句之后、WHERE之前(不能放 SELECT 后) - 多个窗口可逗号分隔:
WINDOW w1 AS (PARTITION BY deptno), w2 AS (PARTITION BY job) - 支持“窗口嵌套”:比如先定义
w1 AS (ORDER BY sal),再用AVG(sal) OVER (w1 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)实现滚动平均 - 注意:
WINDOW定义只作用于当前查询,不能跨语句复用;也不能在子查询里直接引用外部定义的窗口名
GROUPS 窗口帧解决 RANGE 在重复值下的歧义
RANGE 按值范围取行,但遇到重复值(如多个员工 salary=3000)时,RANGE BETWEEN 1 PRECEDING AND CURRENT ROW 可能拉入“逻辑上更早但值相等”的多行,导致结果不稳定。而 GROUPS 按“排序后的位置组”划分:
-
GROUPS BETWEEN 1 PRECEDING AND CURRENT ROW表示:取排序后“当前组前一组”到“当前组”的所有行(相同ORDER BY值视为同一组) - 它和
RANGE的关键区别在于:不依赖具体数值差,只依赖排序后的组序号,对重复值天然鲁棒 - 必须配合
ORDER BY使用,否则报错;且不能与ROWS混用 - 常见误用:把
GROUPS当成“按值去重后再算”,实际它只是分组单位不同,原始行数不变
EXCLUDE 子句精准控制当前行是否参与计算
默认所有窗口函数都包含当前行。但有些场景(比如计算“除自己外的部门平均薪资”),你得显式排除它:
- 四种排除模式:
EXCLUDE CURRENT ROW、EXCLUDE GROUP(排除同排序值的所有行)、EXCLUDE TIES(排除与当前行值相同的其他行)、EXCLUDE NO OTHERS(默认,不排) - 必须跟在
ROWS/RANGE/GROUPS之后,例如:AVG(sal) OVER (PARTITION BY deptno ORDER BY sal EXCLUDE CURRENT ROW) - 注意:
EXCLUDE GROUP和EXCLUDE TIES在ORDER BY列存在 NULL 时行为特殊——NULL 被视为独立组,需提前NVL或COALESCE处理 - 性能影响:排除操作本身不显著拖慢,但若配合大范围
ROWS BETWEEN+EXCLUDE GROUP,可能触发额外排序
真正容易被忽略的是三者组合使用时的优先级:WINDOW 定义基础结构,GROUPS 决定帧内分组粒度,EXCLUDE 最后裁剪参与计算的行——顺序不能颠倒,语法错误往往卡在这一步。











