percentile_cont(0.5)通过线性插值计算中位数,偶数行返回中间两值平均值(如[4,6]→5.0),符合统计定义;percentile_disc(0.5)取排序后靠前的实际值(如[4,6]→4),结果必为原始数据中的某值。

直接用 PERCENTILE_CONT 或 PERCENTILE_DISC 配合 WITHIN GROUP (ORDER BY ...) 就能算出单组的百分位数或中位数;但必须确认数据库支持——MySQL 8.0.13+ 仅支持窗口形式,原生不支持聚合形式;SQLite 完全不支持。
PERCENTILE_CONT(0.5) 和 PERCENTILE_DISC(0.5) 的区别在哪
两者都用于求中位数,但行为不同:
-
PERCENTILE_CONT(0.5)做线性插值:偶数行时返回中间两值的平均值(如 [4,6] → 5.0),结果可能是小数,更符合统计定义 -
PERCENTILE_DISC(0.5)取离散值:直接返回排序后靠前的那个实际值(如 [4,6] → 4),结果一定是原始数据中的某个值 - 输入列必须为数值类型;传入
TEXT或DATE会报错function percentile_cont(double precision) does not exist或类型不匹配 - NULL 值会被自动忽略,不影响插值逻辑
PostgreSQL / Oracle / SQL Server 中按组计算中位数的写法
在这些数据库中,PERCENTILE_CONT 支持聚合形式(即带 WITHIN GROUP、不带 OVER),可直接配合 GROUP BY 使用:
SELECT department, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) AS median_salary, PERCENTILE_DISC(0.75) WITHIN GROUP (ORDER BY salary) AS p75_salary FROM employees GROUP BY department;
注意:
- 不能在同一个
SELECT中混用普通列和WITHIN GROUP聚合,除非该列也在GROUP BY中 - 报错
column "xxx" must appear in the GROUP BY clause就是因为漏写了GROUP BY或多写了未分组列 -
WITHIN GROUP (ORDER BY ...)是强制的,缺了会报错,比如 PostgreSQL 提示PERCENTILE_CONT requires an ORDER BY clause
SQL Server 2022+ 大数据场景推荐 APPROX_PERCENTILE_CONT
当表有千万级以上行、且对精度容忍 ±1.33% 误差时,用近似函数比精确计算快得多、内存占用低:
SELECT region, APPROX_PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY order_amount) AS approx_median FROM orders GROUP BY region;
关键点:
- 只在 SQL Server 2022+、BigQuery、某些新版云数仓中可用;SQL Server 2019 及更早版本不识别该函数
- 不支持窗口形式(即不能写
OVER (PARTITION BY ...)),只能用于聚合上下文 - 无法替代
PERCENTILE_CONT做严格审计或报表,但适合实时看板、A/B 测试快速估算
最容易被忽略的是:PERCENTILE_CONT 在 MySQL 和 SQLite 中根本不是“不可用”,而是“语法合法但行为无效”——MySQL 8.0.13+ 允许它出现在窗口函数中,但不允许出现在 GROUP BY 聚合里;而很多用户复制了 PostgreSQL 的写法却没改引擎,结果查出来全是 NULL 或报错。动手前先 SELECT version(); 确认实际能力,比硬套语法更重要。











