postgresql中计算分组中位数必须用percentile_cont(0.5) within group (order by col)配合group by,漏写within group会报错,误用窗口语法也会失败;结果为numeric型,转整数需::integer(截断非四舍五入)。

不能直接在 GROUP BY 里用 MEDIAN() 或 PERCENTILE_CONT(0.5) 作为普通聚合函数——除非你用对语法,否则必然报错或返回错误结果。
PostgreSQL 必须用 PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ...)
这是唯一合法的聚合写法。漏掉 WITHIN GROUP (ORDER BY ...) 会报错:function percentile_cont(double precision) does not exist;误写成窗口形式如 PERCENTILE_CONT(0.5) OVER (PARTITION BY dept) 会触发 window function call requires a frame specification。
-
ORDER BY字段必须明确指定,且不能是表达式(比如ORDER BY salary * 1.0在某些版本不被接受) - 结果默认是
numeric类型,若需整数,加::integer强转,但注意截断而非四舍五入(3.9::integer → 3) - 分组字段和
ORDER BY字段最好都有索引,否则大表GROUP BY+ 排序性能陡降
MySQL 8.0+ 得靠 ROW_NUMBER() + 子查询模拟
MySQL 没有内置中位数聚合函数,必须手动定位中间位置。常见错误是把窗口函数直接放进 WHERE 或 HAVING —— MySQL 不允许。
- 先用 CTE 或子查询生成带序号和总数的临时表:
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary)和COUNT(*) OVER (PARTITION BY dept) - 取值逻辑必须覆盖奇偶:用
rn IN (FLOOR((cnt + 1)/2), CEIL((cnt + 1)/2)),不能只写rn = cnt/2 + 1 - 最后在外层按分组
AVG(),否则单个偶数分组可能只取到一个值
Oracle 和 SQL Server 的 MEDIAN() / PERCENTILE_CONT() 不能直连 GROUP BY
Oracle 的 MEDIAN(sal) 看似简单,但它不是标准聚合函数——放在 GROUP BY deptno 里会报 ORA-00937;SQL Server 的 PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY sal) 同样不能和 GROUP BY 并列使用。
- 正确姿势是搭配
OVER (PARTITION BY ...),再用DISTINCT去重,例如:SELECT DISTINCT deptno, MEDIAN(sal) OVER (PARTITION BY deptno) - 如果某组所有值都是
NULL,结果为NULL,不是没算出来——业务需要默认值时得显式用NVL()或COALESCE() - SQL Server 中若未建索引,
PERCENTILE_CONT窗口计算可能比手写ROW_NUMBER()更慢
真正跨库安全、逻辑清晰的做法,还是手写 ROW_NUMBER() + 分组计数,尤其当你要兼容 MySQL 5.7、旧版 SQL Server 或做复杂条件过滤时——语法稍长,但行为可控,不会因数据库版本升级突然失效。











