偏度和峰度需基于三阶、四阶中心矩计算,必须使用总体统计量(STDDEV_POP/VAR_POP),PostgreSQL 14+ 支持内置SKEWNESS但需手算KURTOSIS,MySQL/SQL Server须用CTE或子查询先算均值和标准差,注意NULLIF防除零、样本量影响及定义差异。

偏度和峰度的数学定义决定SQL实现方式
偏度(Skewness)衡量分布左右不对称程度,峰度(Kurtosis)衡量尾部厚重程度——两者都依赖三阶、四阶中心矩。标准公式里分母是标准差的幂次,分子是对应阶数的离均差幂次均值。这意味着你无法绕过 AVG、POWER、STDDEV_POP 或手动计算的方差/标准差。
多数数据库不内置 SKEWNESS 或 KURTOSIS 函数(PostgreSQL 14+ 有 SKEWNESS,但 KURTOSIS 仍需手算),所以得组合基础聚合函数。关键点在于:必须用总体统计量(STDDEV_POP、VAR_POP),而非样本统计量(STDDEV_SAMP),否则结果会偏差——尤其小样本时,分母自由度修正会让峰度值系统性偏低。
PostgreSQL 中直接计算偏度和峰度的写法
PostgreSQL 支持 POWER 和窗口函数,适合一次性完成。注意:skewness 是内置函数,但仅限 14+;kurtosis 没有内置,必须手推。
- 偏度(使用内置):
SELECT SKEWNESS(x) FROM t - 峰度(手算,按 Pearson 定义):
SELECT AVG(POWER((x - AVG(x)) / NULLIF(STDDEV_POP(x), 0), 4)) FROM t - 为避免除零,务必用
NULLIF(STDDEV_POP(x), 0)包裹分母 - 如果数据全相同,
STDDEV_POP(x)为 0,不加NULLIF会报division by zero
MySQL 和 SQL Server 需要完全手写公式
这两个系统既无 SKEWNESS 也无 KURTOSIS,且不支持在聚合中嵌套多层 AVG(如 AVG(x - AVG(x)) 会报错)。必须用子查询或 CTE 先算均值和标准差。
以 MySQL 为例(8.0+ 支持 CTE):
WITH stats AS ( SELECT AVG(x) AS mu, STDDEV_POP(x) AS sigma FROM t ) SELECT AVG(POWER((t.x - s.mu) / NULLIF(s.sigma, 0), 3)) AS skewness, AVG(POWER((t.x - s.mu) / NULLIF(s.sigma, 0), 4)) AS kurtosis FROM t CROSS JOIN stats s;
要点:
- 不能把
AVG(x)直接写进POWER里——MySQL 不允许聚合嵌套 -
CROSS JOIN stats是最简方式复用单行统计值 - SQL Server 同理,但需用
STDEV(样本)或STDEVP(总体);务必选STDEVP,否则峰度值会比预期低约 +2(因样本峰度定义减去 3,而 Pearson 峰度不减)
实际应用中容易被忽略的三个细节
偏度/峰度数值本身敏感、易误读,光算出来没用,得结合业务判断。
- 样本量低于 50 时,峰度估计极不稳定——
POWER(..., 4)放大异常值影响,一个离群点就能让峰度虚高 - 偏度接近 0 不代表对称:双峰分布也可能偏度≈0,得看直方图
- 不同系统对“峰度”的定义可能不同:有些软件(如 Excel
KURT)返回的是 excess kurtosis(即 Pearson 峰度减 3),而纯 SQL 手算的是 raw kurtosis;对比时必须确认基准
如果你的字段含大量 NULL,记得所有聚合默认忽略它们,但要确认这是否符合你的业务逻辑——比如缺失值是否应视为 0 或中位数填充,这会显著改变偏度方向。

















