percentile_cont是窗口函数,必须配合within group(order by...)和over(partition by...)使用,用于计算连续分布下的插值中位数(如0.5);不支持mysql,postgresql/sql server/oracle可用,分组结果需额外去重。

PERCENTILE_CONT 语法和基本用法
PERCENTILE_CONT 是窗口函数,不能用于普通聚合(比如 GROUP BY 后直接调用),必须搭配 OVER() 使用。它返回连续分布下的插值百分位数,比如中位数就是 PERCENTILE_CONT(0.5)。常见错误是写成 SELECT PERCENTILE_CONT(0.5) FROM t GROUP BY x —— 这会报错,因为缺少 OVER 子句。
正确结构是:PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY col) OVER (PARTITION BY group_col)。注意两个关键部分:WITHIN GROUP (ORDER BY ...) 指定排序依据(必填),OVER (PARTITION BY ...) 指定分组维度(可选,但分组时必须有)。
分组计算中位数的典型写法
想按部门算薪资中位数?不能用 GROUP BY dept 配合 PERCENTILE_CONT,而要用窗口函数 + 去重。常见做法是先算出每个分组的中位数值,再用 DISTINCT ON(PostgreSQL)或 ROW_NUMBER 辅助去重(其他数据库)。
- PostgreSQL 示例:
SELECT DISTINCT ON (dept) dept, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) OVER (PARTITION BY dept) AS median_salary FROM employees;
- 通用兼容写法(避免
DISTINCT ON):SELECT dept, median_salary FROM ( SELECT dept, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) OVER (PARTITION BY dept) AS median_salary, ROW_NUMBER() OVER (PARTITION BY dept) AS rn FROM employees ) t WHERE rn = 1;
(注意:这里rn = 1只是占位,实际每组所有行的median_salary值相同,所以任取一行即可)
常见报错和兼容性陷阱
MySQL 不支持 PERCENTILE_CONT(8.0+ 仍无),SQL Server 支持但要求兼容级别 ≥ 110;Oracle 和 PostgreSQL 支持完整语法。遇到 ERROR: window function PERCENTILE_CONT requires an ORDER BY clause within WITHIN GROUP,说明漏了 WITHIN GROUP (ORDER BY ...) —— 它不是可选的。
-
PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY score)必须指定ORDER BY,且该列不能为NULL(否则该行被忽略) - 如果分组内只有 1 行,结果就是该行的值;若全为
NULL,结果为NULL - 传入的百分数必须在 0.0 到 1.0 之间,
PERCENTILE_CONT(1.1)会报错
和 PERCENTILE_DISC 的关键区别
PERCENTILE_CONT 插值计算,结果可能是原始数据里不存在的值(比如 [10,20] 的 0.5 位是 15.0);PERCENTILE_DISC 返回实际存在的离散值(同样数据下返回 10 或 20)。选哪个取决于业务需求:要“理论中位数”用 CONT,要“真实存在的中间样本”用 DISC。
性能上,两者开销接近,但 CONT 需要做浮点运算和线性插值,极端高基数分组时略慢。另外,PERCENTILE_CONT 对 ORDER BY 列的排序稳定性更敏感——如果排序列有大量重复值,插值位置可能因排序实现差异而微调。
真正容易被忽略的是:即使你写了 PARTITION BY,PERCENTILE_CONT 仍会为每一行返回相同分组结果,不是“每组只出一行”。要不要去重、怎么去重,得由你控制。











