sql标准无median()窗口函数,主流数据库均不支持median() over(...)语法;可靠做法是用percentile_cont(0.5) within group或row_number()+count()手动定位中间位置。

SQL标准里根本没有MEDIAN窗口函数
别被某些文档或IDE的自动补全骗了——MEDIAN 不是 SQL 标准支持的窗口函数,PostgreSQL、SQL Server、Oracle 等主流数据库都不提供 MEDIAN() OVER (...) 这种语法。你执行它大概率会报错:ERROR: function median(...) does not exist 或类似提示。
真正能用窗口逻辑算中位数,得靠排序+行号+条件判断组合实现,不同数据库写法差异还很大。
PostgreSQL 中用 PERCENTILE_CONT 实现分组中位数
PostgreSQL 提供了 PERCENTILE_CONT 聚合函数,配合 GROUP BY 可以间接模拟“窗口中位数”效果;若真要窗口式(即每行返回所在分组的中位数),必须嵌套 ROW_NUMBER() + COUNT() 手动定位中间位置。
-
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY value)是唯一可靠且语义清晰的中位数计算方式,但它是聚合函数,不能直接加OVER - 想在每行显示同组中位数?得用子查询或
LATERAL关联:先按group_id分组算一次中位数,再和原表JOIN - 注意:如果分组内有
NULL,PERCENTILE_CONT默认忽略它们,但ORDER BY子句不显式写NULLS LAST可能导致排序行为不符合预期
MySQL 和 SQL Server 必须手写中位数逻辑
MySQL 8.0+ 有窗口函数,但没内置中位数;SQL Server 同样缺失。两者都得靠 ROW_NUMBER() 和 COUNT() OVER (PARTITION BY ...) 配合判断奇偶。
- 核心思路:对每组数据按值排序,算出总行数
n,取第FLOOR((n+1)/2)和CEILING((n+1)/2)行的平均值(兼容奇偶) - 容易漏掉的边界:当某组只有一行时,两个序号相同,平均值就是它自己;但若该行值为
NULL,结果就是NULL,不是 0 - 性能隐患:对大表分组排序开销高,没有索引支撑
ORDER BY group_id, value时可能很慢
别硬套“窗口中位数”,先确认是否真需要每行重复值
多数业务场景其实只要每组一个中位数值(比如报表汇总),用 GROUP BY + PERCENTILE_CONT(PG)或子查询(MySQL/SQL Server)就够了。强行用窗口函数让每行都带一遍中位数,除了增加计算量,还容易误导后续逻辑误以为这是动态可变的指标。
更隐蔽的问题是:中位数对空值和重复值敏感,而 ROW_NUMBER() 不去重,RANK() 又会导致序号跳跃——选哪个编号函数,直接影响中间位置的选取结果。











