VAR()与VARIANCE()完全等价,均默认计算样本方差(n−1);真正区分的是VAR_SAMP()(样本)和VAR_POP()(总体);二者需与对应STDDEV函数配对使用,且NULL值会被自动忽略导致结果偏差。

VAR() 和 VARIANCE() 本质是同一个函数,别被名字绕晕
很多用户看到 VAR()、VARIANCE()、VAR_SAMP()、VAR_POP() 就以为是四个独立“偏门”函数,其实不是:VARIANCE() 是标准 SQL 别名,多数数据库(PostgreSQL、SQL Server 2022+、MySQL 8.0+)里它和 VAR() 完全等价,都默认计算样本方差(即除以 n−1)。真正有区分度的是 VAR_SAMP() 和 VAR_POP() —— 前者明确强调“样本”,后者强调“总体”。
实操建议:
-
VAR()和VARIANCE()可互换,选一个保持团队风格统一就行 - 如果业务口径明确是总体(比如全量用户、全年数据无抽样),优先用
VAR_POP(),避免被审计质疑自由度偏差 - 别在旧版 MySQL(如 5.7)里直接写
VAR(),会报错FUNCTION VAR does not exist,得降级用AVG(POWER(x - AVG(x), 2))
GROUP BY 后数值列含 NULL,方差结果会悄悄缩水
VAR() 类函数自动跳过 NULL 值,不报错也不提示,但会导致参与计算的行数远少于你预期的分组大小。例如某部门 100 人,其中 30 条 salary 是 NULL,VAR(salary) 实际只基于 70 个非空值算,结果偏低且不可比。
排查与应对:
- 用
COUNT(salary)和COUNT(*)对比,确认非空参与率 - 若需把 NULL 当 0 处理(如未发薪视为 0),必须显式写成
VAR(COALESCE(salary, 0)) - 若 NULL 代表“未知”,且不能假设为 0,就该在上游清洗阶段补全或打标,而不是在聚合层硬转
STDDEV() 默认是样本标准差,和 VAR() 的自由度逻辑严格对应
方差和标准差是一对绑定函数:STDDEV() = SQRT(VAR()),二者都默认按样本(n−1)计算。很多人单独记住 STDDEV_POP() 却忘了 VAR_POP(),导致波动率口径不一致——比如报表里方差用总体、标准差用样本,数值就对不上。
关键配对关系:
-
VAR()↔STDDEV()(都是样本) -
VAR_POP()↔STDDEV_POP()(都是总体) -
VAR_SAMP()↔STDDEV_SAMP()(同上,语义更显式) - 混用
VAR_POP()+STDDEV()会引入系统性偏差,尤其在小分组(n
分组字段本身含 NULL 时,GROUP BY 会把它聚成单独一组
这是容易被忽略的边界行为:GROUP BY dept 中,所有 dept IS NULL 的记录会被归入同一组(显示为 NULL),而 VAR(salary) 在这组里照常计算——只要该组有 ≥2 个非空 salary 值,就能出有效方差。
但问题在于:这组往往业务含义模糊(“部门未填”不等于“虚拟部门”),却和其他真实部门并列展示,误导分析结论。
稳妥做法:
- 提前过滤:
WHERE dept IS NOT NULL,确保分组维度干净 - 或显式排除:
HAVING COUNT(dept) > 0(注意这不是万能解,因COUNT(dept)不统计 NULL,此处仅作示意) - 若必须保留 NULL 分组,应在报表层加注释说明其构成,避免被当作有效业务单元解读











