SQL无内置SKEWNESS/KURTOSIS函数,需手动计算:偏度=m3/POWER(m2,1.5),峰度=m4/POWER(m2,2)-3(超额);注意总体标准差、溢出及引擎语法差异。

SQL里没有内置的SKEWNESS和KURTOSIS函数
绝大多数主流SQL引擎(PostgreSQL、MySQL、SQL Server、Oracle)都不直接支持SKEWNESS或KURTOSIS聚合函数。你查文档会发现,连pg_statistic视图里存的也只是统计快照,不是实时可调用的聚合能力。想分组算偏度/峰度,必须手动实现三阶/四阶中心矩公式。
手动计算偏度:用AVG、POWER和COUNT组合
偏度 = 三阶中心矩 / 标准差³,分子是AVG(POWER(x - AVG(x), 3)),但注意:必须用总体标准差(除以COUNT(*)而非COUNT(*)-1),否则结果和Python的scipy.stats.skew(..., bias=False)对不上。
- 先算均值:
AVG(x) AS mu - 再算三阶中心矩:
AVG(POWER(x - mu, 3)) AS m3 - 标准差平方(二阶中心矩):
AVG(POWER(x - mu, 2)) AS m2 - 最终偏度:
m3 / POWER(m2, 1.5)(前提是m2 > 0)
PostgreSQL示例:
SELECT
category,
AVG(x) AS mu,
AVG(POWER(x - AVG(x) OVER (PARTITION BY category), 3)) /
POWER(AVG(POWER(x - AVG(x) OVER (PARTITION BY category), 2)), 1.5) AS skewness
FROM data GROUP BY category;
峰度要小心“超额峰度”定义差异
SQL里手算的峰度默认是原始峰度(kurtosis),而Pandas/SciPy默认返回超额峰度(kurtosis minus 3)。如果你需要和Python对齐,得显式减3。
- 四阶中心矩:
AVG(POWER(x - mu, 4)) AS m4 - 原始峰度:
m4 / POWER(m2, 2) - 超额峰度:
m4 / POWER(m2, 2) - 3 - MySQL不支持窗口函数嵌套,得用两层子查询;BigQuery可用
AVG(x) OVER()简化
常见翻车点:POWER(x, 4)在x为负大数时可能溢出(尤其MySQL的DOUBLE精度),建议加WHERE ABS(x) 兜底。
性能与精度陷阱:别在大数据量上直接套公式
一次扫描无法同时拿到AVG(x)和POWER(x - AVG(x), 3)——因为AVG(x)本身是聚合结果,不能在同级表达式中被引用。所有方案都依赖窗口函数或子查询,导致执行计划多趟扫描。
- PostgreSQL/Redshift:用
AVG(x) OVER(PARTITION BY g)最省事 - MySQL 8.0+:支持窗口函数,但
POWER对NULL敏感,务必加WHERE x IS NOT NULL - Spark SQL:可用
skewness()和kurtosis()内置函数(注意是超额峰度),但只支持单列,不能GROUP BY后直接调用,得配合agg()结构
真正上生产前,先用EXPLAIN ANALYZE看是否触发临时表或磁盘排序——偏度/峰度计算本身不重,但分组键高基数 + 数据倾斜时,中间结果膨胀很致命。











