percentile_cont是sql标准中用于计算连续分布分位数的窗口函数,传入0.5时即得中位数,通过线性插值在排序后相邻值间估算(偶数行取平均、奇数行取中间值),必须配合order by使用且参数须为0.5而非50或'0.5'。

PERCENTILE_CONT 是什么,它和中位数有什么关系
PERCENTILE_CONT 是 SQL 标准中的窗口函数,用于在有序数据集上插值计算连续分布的分位数。中位数就是第 50 百分位(即 PERCENTILE_CONT(0.5)),但它不是简单取中间位置的值,而是在排序后两个相邻值之间线性插值——尤其当行数为偶数时,结果才是真正的数学中位数。
注意:它必须配合 ORDER BY 子句使用,且只支持窗口函数语法(不能直接写在 SELECT 列表里而不带 OVER)。
不同数据库对 PERCENTILE_CONT 的支持差异
- PostgreSQL、Oracle、SQL Server(2012+)、Snowflake、BigQuery(需开启标准 SQL)都支持
PERCENTILE_CONT
- MySQL 完全不支持,得用变量或子查询模拟
- SQLite 不支持
- Redshift 支持但仅限于
PERCENTILE_CONT(0.5),且必须搭配 GROUP BY 或窗口框架
PERCENTILE_CONT
PERCENTILE_CONT(0.5),且必须搭配 GROUP BY 或窗口框架常见错误现象:ERROR: function percentile_cont(double precision) does not exist —— 多半是 PostgreSQL 中没加 OVER(),或传入了非数值列。
怎么写一个可靠的中位数查询(以 PostgreSQL 为例)
假设有一张 sales 表,字段为 amount(数值型):
- 必须用
OVER (ORDER BY amount),不能省略括号内的排序 - 返回的是单个标量值,所以通常配合
SELECT DISTINCT或聚合层使用 - 若想按分组算中位数(比如每个部门的销售额中位数),要用
PARTITION BY dept_id
SELECT DISTINCT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount) AS median_amount FROM sales;
如果要分组:
SELECT dept_id, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount) AS median_amount FROM sales GROUP BY dept_id;
关键点:
-
WITHIN GROUP (ORDER BY ...)是标准写法,不是OVER (ORDER BY ...)(后者是窗口函数变体,仅 Snowflake/BigQuery 等支持) -
PERCENTILE_CONT的参数必须是常量表达式(如0.5),不能是列或变量 - 排序字段必须是可比较的数值或时间类型;对文本用它会报错或返回无意义结果
容易被忽略的边界情况和性能影响
- NULL 值默认被排除在外,不需要额外
WHERE amount IS NOT NULL,但如果你显式过滤了 NULL,结果可能和未过滤时一致——别误以为漏了数据
- 数据量极大时(千万级以上),
PERCENTILE_CONT 在某些引擎(如 PostgreSQL)内部会构建完整排序,可能吃内存;比起 APPROX_MEDIAN(如 BigQuery)慢得多
- 在 SQL Server 中,若未指定
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING,默认窗口范围可能出人意料,建议显式写全
- 如果你看到结果是
NaN 或空,先检查源字段是否全为 NULL,或类型是否意外转成了 text/varchar
WHERE amount IS NOT NULL,但如果你显式过滤了 NULL,结果可能和未过滤时一致——别误以为漏了数据PERCENTILE_CONT 在某些引擎(如 PostgreSQL)内部会构建完整排序,可能吃内存;比起 APPROX_MEDIAN(如 BigQuery)慢得多ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING,默认窗口范围可能出人意料,建议显式写全NaN 或空,先检查源字段是否全为 NULL,或类型是否意外转成了 text/varchar中位数看着简单,但 PERCENTILE_CONT 的行为高度依赖数据库实现细节,尤其是 WITHIN GROUP 和 OVER 两种语法混用时,很容易查出错值。动手前最好在小数据集上验证输出是否符合手算预期。











