如何用SQL的STDDEV和VARIANCE函数计算分组内标准差与方差?
- 内容介绍
- 相关推荐
本文共计649个文字,预计阅读时间需要3分钟。
直接说结论:
为什么 GROUP BY 后结果看起来不对?常见偏差来源
典型现象:分组后 STDDEV(sales) 值比手动用 Excel 或 Python 算的「总体标准差」大一点——大概率是因为你没意识到默认是样本算法。
-
STDDEV(x)≡STDDEV_SAMP(x):分母是COUNT(x) - 1 -
STDDEV_POP(x):分母是COUNT(x),才是数学定义的总体标准差 - 当某组只有 1 行时,
STDDEV(x)返回NULL(因为除零),而STDDEV_POP(x)返回0 - MySQL 8.0+、PostgreSQL、Oracle 都支持这四者;SQLite 只有
stddev(即样本)和stdev_pop(需启用扩展)
实际写法:带条件的分组统计示例
假设有一张销售表 sales_data,字段为 region、amount,想按地区看销售额的标准差与方差:
SELECT region, AVG(amount) AS avg_amount, STDDEV(amount) AS stddev_sample, -- 样本标准差 VARIANCE(amount) AS var_sample, -- 样本方差(= stddev²) STDDEV_POP(amount) AS stddev_pop, -- 总体标准差 VARIANCE_POP(amount) AS var_pop -- 总体方差 FROM sales_data WHERE amount IS NOT NULL GROUP BY region;
注意:VARIANCE(x) 就是 POWER(STDDEV(x), 2),不是独立算法;两者必须同为 SAMP 或 POP 版本才匹配。
容易被忽略的 NULL 和数据类型问题
这两个函数会自动忽略 NULL 值,但不会报错或警告——如果你的字段本应非空却出现大量 NULL,分母变小会导致标准差虚高。
- 确保
amount类型是数值型(如DECIMAL、FLOAT),否则某些数据库(如 PostgreSQL)会报错function stddev(numeric) does not exist - 若字段含字符串数字(如
'123.45'),必须先CAST(amount AS NUMERIC),否则多数数据库不隐式转换 - PostgreSQL 中
STDDEV对INT输入返回DOUBLE PRECISION;若后续要比较或导出,留意精度是否满足需求
最常踩的坑其实是没核对业务定义——到底要反映“这群数据自身的离散程度”(用 POP),还是“用这组样本来推断更大群体”(用 SAMP)。选错一个字母,结果就差个百分之几,报表上线后才发现就得重跑。
本文共计649个文字,预计阅读时间需要3分钟。
直接说结论:
为什么 GROUP BY 后结果看起来不对?常见偏差来源
典型现象:分组后 STDDEV(sales) 值比手动用 Excel 或 Python 算的「总体标准差」大一点——大概率是因为你没意识到默认是样本算法。
-
STDDEV(x)≡STDDEV_SAMP(x):分母是COUNT(x) - 1 -
STDDEV_POP(x):分母是COUNT(x),才是数学定义的总体标准差 - 当某组只有 1 行时,
STDDEV(x)返回NULL(因为除零),而STDDEV_POP(x)返回0 - MySQL 8.0+、PostgreSQL、Oracle 都支持这四者;SQLite 只有
stddev(即样本)和stdev_pop(需启用扩展)
实际写法:带条件的分组统计示例
假设有一张销售表 sales_data,字段为 region、amount,想按地区看销售额的标准差与方差:
SELECT region, AVG(amount) AS avg_amount, STDDEV(amount) AS stddev_sample, -- 样本标准差 VARIANCE(amount) AS var_sample, -- 样本方差(= stddev²) STDDEV_POP(amount) AS stddev_pop, -- 总体标准差 VARIANCE_POP(amount) AS var_pop -- 总体方差 FROM sales_data WHERE amount IS NOT NULL GROUP BY region;
注意:VARIANCE(x) 就是 POWER(STDDEV(x), 2),不是独立算法;两者必须同为 SAMP 或 POP 版本才匹配。
容易被忽略的 NULL 和数据类型问题
这两个函数会自动忽略 NULL 值,但不会报错或警告——如果你的字段本应非空却出现大量 NULL,分母变小会导致标准差虚高。
- 确保
amount类型是数值型(如DECIMAL、FLOAT),否则某些数据库(如 PostgreSQL)会报错function stddev(numeric) does not exist - 若字段含字符串数字(如
'123.45'),必须先CAST(amount AS NUMERIC),否则多数数据库不隐式转换 - PostgreSQL 中
STDDEV对INT输入返回DOUBLE PRECISION;若后续要比较或导出,留意精度是否满足需求
最常踩的坑其实是没核对业务定义——到底要反映“这群数据自身的离散程度”(用 POP),还是“用这组样本来推断更大群体”(用 SAMP)。选错一个字母,结果就差个百分之几,报表上线后才发现就得重跑。

