postgresql原生不支持skewness和kurtosis函数,需手写sql实现:用cte先算均值和stddev_pop,再分别计算三阶/四阶中心矩并除以对应标准差幂次,注意使用stddev_pop而非stddev_samp,并区分原始峰度与超额峰度。

PostgreSQL 里直接用 SKEWNESS 和 KURTOSIS?别试了,根本不存在
PostgreSQL 原生不支持 SKEWNESS 或 KURTOSIS 聚合函数。你执行 SELECT SKEWNESS(x) FROM t; 会直接报错:ERROR: function skewness(numeric) does not exist。这不是拼写问题,是压根没实现。MySQL、SQLite 同样没有;SQL Server 有 STDEV 但也没内置偏度峰度。真要算,得自己推公式或借扩展。
用 pg_stat_statements 扩展?不行,那是查查询统计的
有人看到 “stat” 就联想,其实 pg_stat_statements 跟数据分布统计完全无关——它只记录 SQL 执行次数、耗时、IO 等元信息。想靠它算偏度?连数据列都碰不到。真正能用的只有两种路:
- 手写 SQL 实现三阶/四阶中心矩(推荐,纯 SQL,无依赖)
- 装
tablefunc或第三方扩展(如aggs_for_vecs),但多数生产环境禁用扩展
除非 DBA 明确允许且已启用,否则别指望靠一个 CREATE EXTENSION 解决问题。
手算偏度:核心是 AVG、POWER 和 COUNT 的组合
偏度公式本质是「三阶标准中心矩」:SKEW = E[(X−μ)³] / σ³。SQL 里得拆成五步算,每一步都容易漏掉校正:
- 先算均值
AVG(x)和标准差STDDEV_POP(x)(注意不是STDDEV_SAMP,分母要用 N 不是 N−1) - 用
POWER(x - avg_x, 3)算每个点的三阶偏差,再AVG()得三阶中心矩 - 最后除以
POWER(stddev_pop_x, 3)—— 这里最容易错:如果用STDDEV_SAMP,结果会系统性偏高 - 整段必须用子查询或 CTE,否则
AVG和STDDEV_POP不能在同层引用
示例(PostgreSQL):
WITH stats AS ( SELECT AVG(x) AS mu, STDDEV_POP(x) AS sigma FROM t ) SELECT AVG(POWER(t.x - stats.mu, 3)) / POWER(stats.sigma, 3) AS skewness FROM t, stats;
峰度要小心「超额峰度」还是「原始峰度」
SQL 里算峰度,公式是 KURT = E[(X−μ)⁴] / σ⁴,但多数统计软件(如 Python 的 scipy.stats.kurtosis)默认返回「超额峰度」(减去 3),而 SQL 手算出来的是原始峰度。这意味着:
- 如果你对比 Python 结果发现差 3,不是算错了,是定义不同
- 正态分布原始峰度为 3,超额峰度才是 0 —— 生产中报告时得确认业务方要哪一种
- 同样必须用
STDDEV_POP,且四阶幂运算对离群值极敏感,空值或极端值会直接拉爆结果
峰度 SQL 只比偏度多一行:AVG(POWER(t.x - stats.mu, 4)) / POWER(stats.sigma, 4),但分母是四次方,数值溢出风险更高,尤其当 sigma 很小、x 范围很大时。
偏度和峰度都不是“算出来就行”的指标:它们对缺失值、异常值、样本量极度敏感。100 行数据算出来的峰度,可能比 10000 行的置信度还低。上线前务必用已知分布的数据(比如生成正态随机数)交叉验证 SQL 结果是否合理。










