主流数据库均不支持stddev() over语法;postgresql、oracle、mysql 8.0+、bigquery仅支持stddev_samp()或stddev_pop()的窗口版本,sql server需手动实现。

STDDEV() OVER 在主流数据库里根本不存在
直接说结论:PostgreSQL、Oracle、SQL Server 都不支持 STDDEV() OVER 这种写法。MySQL 8.0+ 虽然支持窗口函数,但 STDDEV() 本身是聚合函数,不能直接加 OVER;它只提供 STDDEV_SAMP() 和 STDDEV_POP() 的窗口版本。
常见错误现象是执行时报错:function stddev(double precision) does not exist(PostgreSQL)或 Incorrect syntax near 'OVER'(SQL Server)。这不是你写错了,是语法根本不被支持。
用 STDDEV_SAMP() 或 STDDEV_POP() 替代,注意样本 vs 总体语义
所有支持窗口版标准差的数据库(PostgreSQL、Oracle、MySQL 8.0+、BigQuery)都要求显式指定计算方式:
-
STDDEV_SAMP() OVER (...):按「样本标准差」计算(分母为 n−1),适用于从总体中抽样分析 -
STDDEV_POP() OVER (...):按「总体标准差」计算(分母为 n),适用于你手上的数据就是全部数据集
例如在 PostgreSQL 中统计每个部门薪资的标准差(样本):
SELECT name, dept, salary, STDDEV_SAMP(salary) OVER (PARTITION BY dept) AS dept_salary_stddev_samp FROM employees;
如果误用 STDDEV_POP() 去分析抽样数据,结果会系统性偏小;反过来用 STDDEV_SAMP() 算全量数据(比如公司全员薪资),又会轻微高估离散程度。
MySQL 8.0+ 必须用 _SAMP / _POP 后缀,且不支持简写
MySQL 完全不认 STDDEV() 作为窗口函数,连别名映射都不做。以下写法全报错:
-
STDDEV(salary) OVER (PARTITION BY dept)→ 错误 -
STDDEV_SAMP(salary) OVER (PARTITION BY dept)→ 正确 -
STD(salary) OVER (...)→ MySQL 不支持这个别名
另外注意:MySQL 的 STDDEV_SAMP() 窗口函数要求至少 2 行数据参与计算,否则返回 NULL(不是 0)。单行分区会直接丢失该字段值,这点容易在分组后漏掉异常情况。
SQL Server 没有原生窗口版标准差,得绕路
SQL Server 直到 2022 版仍不支持任何 STDDEV_* 窗口函数。必须手动组合 AVG() 和 SUM() 实现:
SELECT
name,
dept,
salary,
SQRT(
SUM(POWER(salary - AVG(salary) OVER (PARTITION BY dept), 2))
OVER (PARTITION BY dept)
/ NULLIF(COUNT(*) OVER (PARTITION BY dept) - 1, 0)
) AS dept_stddev_samp
FROM employees;
这里的关键坑是:
- 必须用
NULLIF(..., 0)防止除零错误 -
POWER(..., 2)比* ... * ...更安全,避免大数溢出 - 嵌套的
OVER子句性能较差,数据量大时明显慢于原生函数
实际项目中,如果标准差只是中间指标,建议改在应用层计算——尤其是当分区粒度细、行数少的时候,比硬写 SQL 更稳。











