sql中stddev()和variance()可直接计算分组标准差与方差,但各数据库对样本/总体标准差默认实现不同:postgresql、oracle默认样本(n−1),mysql默认总体(n),sql server用stdev/stdevp区分;null值被自动忽略,需用count(col)核验有效行数;sqlite不支持需手动计算或启用math扩展;方差单位为平方,比较离散程度应优先用变异系数stddev()/avg()。

SQL里直接用 STDDEV() 和 VARIANCE() 就能算分组后的标准差与方差
绝大多数主流数据库(PostgreSQL、Oracle、MySQL 8.0+、SQL Server)都内置了聚合函数,不需要手写公式。但要注意:不同数据库对「样本标准差」和「总体标准差」的默认实现不同,容易算错。
-
STDDEV()在 PostgreSQL 和 Oracle 中默认是样本标准差(除以 n−1),等价于STDDEV_SAMP() - MySQL 的
STDDEV()和STDDEV_POP()是别名关系,默认是总体标准差(除以 n);真正要样本标准差得用STDDEV_SAMP() - SQL Server 只提供
STDEV()(样本)和STDEVP()(总体),命名更直白 - 如果分组字段含 NULL,这些函数会自动跳过对应行——但不会报错,容易误以为数据全参与了计算
GROUP BY 后必须确保数值列非 NULL,否则结果偏小
标准差对方差敏感,而 STDDEV() 遇到 NULL 值直接忽略该行。如果某组里有大量 NULL,实际参与计算的行数远少于 COUNT(*),但函数不提示。
- 用
COUNT(col)查看实际参与计算的非 NULL 行数,和COUNT(*)对比 - 若需把 NULL 当 0 处理,得先用
COALESCE(col, 0)转换再聚合 - 例如:
SELECT dept, STDDEV(COALESCE(salary, 0)) FROM emp GROUP BY dept
SQLite 不支持 STDDEV(),得手动算或改用扩展
SQLite 原生没提供标准差函数,强行用会导致 no such function: STDDEV 错误。不能靠 CAST 或子查询绕过,必须换思路。
- 最简方案:用
sqrt(avg(x*x) - avg(x)*avg(x))近似总体标准差(要求数据无 NULL,且组内至少 2 行) - 更稳妥做法:启用 SQLite 的 math 扩展(需编译时开启或加载
math.so),然后用math_stddev() - 生产环境建议避开 SQLite 做统计分析,换 PostgreSQL 或加一层应用层计算
方差和标准差结果单位不同,别混着比大小
方差是平方单位(比如工资方差单位是「元²」),标准差才是和原始数据同单位。直接拿 VARIANCE() 和均值比,数值会大得多,容易误判离散程度。
- 比较离散程度时,优先用
STDDEV()/AVG()算变异系数(CV),它无量纲 - 导出结果时注意字段命名:别把
VARIANCE(salary)的结果标成「平均薪资波动」,这是常见误导 - 如果下游是 BI 工具,确认其是否把
STDDEV_POP和STDDEV_SAMP当作同一指标处理——有些工具默认按样本算,但数据其实是总体
标准差和方差看着简单,但数据库实现细节、NULL 处理、单位混淆这三处最容易在上线后暴露问题。尤其跨库迁移时,STDDEV() 行为不一致几乎必踩。











