能,但必须配合partition by明确“阶段”边界;不写partition by则返回全表最大值,而非阶段内最大值;max over保留原始行并新增阶段最大值列,适用于对比、标记或过滤,且需注意order by会使其变为累计最大值而非静态最大值。

MAX OVER 能不能直接拿到每个阶段的最高值?
能,但必须配合 PARTITION BY 明确“阶段”边界。不写 PARTITION BY 就是全表最大值,不是阶段内最大值——这是最常踩的坑。
比如按部门分阶段查薪资最高值,MAX(salary) OVER (PARTITION BY dept) 才对;如果漏掉 PARTITION BY dept,所有人看到的都是全公司最高薪,和“阶段”完全无关。
为什么用 MAX OVER 而不是 GROUP BY?
因为 GROUP BY 会压缩行数,丢失原始记录细节;MAX OVER 是“原样保留每一行 + 多一列阶段最大值”,适合做对比、标记或过滤。
典型场景:
- 标记某员工是否为本部门薪资最高者(
CASE WHEN salary = MAX(salary) OVER (PARTITION BY dept) THEN 'TOP' END) - 计算个人薪资占部门最高薪的比例(
salary / MAX(salary) OVER (PARTITION BY dept)) - 保留时间序列中每季度的最高销售额,同时保留每天明细
ORDER BY 在 MAX OVER 里起什么作用?
加了 ORDER BY 就变成“累计最大值”,不是阶段静态最大值。例如:MAX(salary) OVER (PARTITION BY dept ORDER BY hire_date) 返回的是“入职时间不晚于当前行的最高薪”,不是整个部门的最高薪。
要阶段静态最大值,就别写 ORDER BY;真需要累计效果,得确认业务逻辑是否真要“随时间递进的最大值”。
常见错误现象:MAX(...) OVER (PARTITION BY x ORDER BY y) 结果逐行变化,但你以为它该恒定——本质是窗口帧默认为 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW。
不同数据库对 MAX OVER 的兼容性差异
MAX OVER 在 PostgreSQL、SQL Server、Oracle、Snowflake、BigQuery 中都支持;MySQL 8.0+ 支持,5.7 及更早版本不支持,会报错 ERROR 1064: This version of MySQL doesn't yet support 'WINDOW'。
性能上要注意:如果 PARTITION BY 字段未建索引,且数据量大,窗口函数可能比等价的关联子查询还慢——不是语法问题,是执行计划问题。实操建议先看 EXPLAIN,尤其注意是否出现 WindowAgg 或大量临时表扫描。
另外,MAX 对 NULL 安全:自动忽略 NULL 值;但如果整组全是 NULL,结果就是 NULL,不是 0 或空字符串——这点容易在后续计算中引发意外空值传播。










