covar_pop是计算总体协方差的聚合函数,即基于全部数据、分母为n的协方差;其公式为avg(xy) - avg(x)avg(y),要求两个数值表达式成对非null才参与计算,结果为number类型,全空则返回null。

COVAR_POP 是什么,它算的是哪个协方差?
COVAR_POP 计算的是总体协方差(population covariance),即基于全部数据而非样本的协方差。它默认把输入的两列当作完整总体,分母用 n(行数),不是 n-1。如果你的数据本身就是全量业务数据(比如某月所有订单的销售额和利润),用 COVAR_POP 合理;如果是抽样数据,更常用的是 COVAR_SAMP。
- 协方差公式为:
AVG(x <em> y) - AVG(x) </em> AVG(y),COVAR_POP内部正是按这个逻辑实现的 - 必须传入两个数值表达式,且成对非 NULL 才参与计算
- 如果所有行中任意一列为 NULL,则该行被跳过;若无有效行,结果为 NULL
怎么写 COVAR_POP 的基本语法?
直接在 SELECT 或聚合上下文中调用,不能用于窗口函数(多数数据库不支持 COVAR_POP() OVER(...),PostgreSQL 14+ 才开始实验性支持):
SELECT COVAR_POP(sales_amount, profit) FROM orders WHERE order_date >= '2024-01-01';
- 参数顺序敏感:第一个是 X,第二个是 Y,交换后结果不变(协方差对称),但语义上别弄反业务含义
- 不支持常量或标量子查询作为参数,例如
COVAR_POP(100, column)会报错 - 若表中存在大量 NULL 值,实际参与计算的行数可能远少于预期,建议先用
COUNT(*)和COUNT(column1, column2)对比确认
常见错误:为什么 COVAR_POP 返回 NULL 或 0?
-
COVAR_POP 返回 NULL 的典型原因:
- 输入的两列在所有行中至少有一列为 NULL(即没有一对非 NULL 的
(x, y))
- 表为空,或
WHERE 条件过滤后无数据
- 返回 0 并不意味着无相关性,只说明线性协方差为 0(可能呈非线性关系,或数据本身均值极低)
- 在 MySQL 8.0.22 之前不支持
COVAR_POP,会报错 FUNCTION xxx.COVAR_POP does not exist;需改用等价表达式 AVG(x<em>y) - AVG(x)</em>AVG(y)
- PostgreSQL 对
COVAR_POP 要求两列同为数值类型,若其中一列为 TEXT 且含数字字符串,必须显式 ::NUMERIC 转换,否则报错 function covar_pop(text, numeric) does not exist
和 COVAR_SAMP 一起用时要注意什么?
COVAR_POP 返回 NULL 的典型原因: - 输入的两列在所有行中至少有一列为 NULL(即没有一对非 NULL 的
(x, y)) - 表为空,或
WHERE条件过滤后无数据
COVAR_POP,会报错 FUNCTION xxx.COVAR_POP does not exist;需改用等价表达式 AVG(x<em>y) - AVG(x)</em>AVG(y) COVAR_POP 要求两列同为数值类型,若其中一列为 TEXT 且含数字字符串,必须显式 ::NUMERIC 转换,否则报错 function covar_pop(text, numeric) does not exist COVAR_POP 和 COVAR_SAMP 仅在分母上不同:前者除以 n,后者除以 n-1。当 n = 1 时,COVAR_SAMP 返回 NULL(因分母为 0),而 COVAR_POP 返回 0(因分子也为 0)。
- 实际使用中,如果不确定数据是否为总体,优先查清业务背景;误用
COVAR_POP代替COVAR_SAMP会导致低估离散程度 - 多数 BI 工具(如 Metabase、Superset)的协方差字段默认调用的是
COVAR_SAMP,直接写 SQL 时容易忽略这个差异 - 在同一查询中混用二者无意义,但可以并列输出对比:
SELECT COVAR_POP(x, y) AS pop_cov, COVAR_SAMP(x, y) AS samp_cov FROM data;
协方差本身量纲依赖原始单位,单独看数值大小没意义;真正关键的是符号(正/负)和后续标准化得到的相关系数。别只盯着 COVAR_POP 的输出数字,忘了做 CORR 或标准化处理。











