如何在MySQL中用CASE WHEN计算中位数?以station表LAT_N列为例
用CASE WHEN在MySQL中计算LAT_N列的中位数
嘿,我来帮你搞定这个需求!MySQL本身没有内置的中位数函数,但我们可以结合排序、定位逻辑,用CASE WHEN来区分总行数奇偶的不同场景,精准算出station表LAT_N列的中位数。
核心思路
- 先给LAT_N列排序,给每一行分配一个唯一序号;
- 获取总行数,判断奇偶性:
- 奇数行时,中位数就是排序后正中间那一行的LAT_N值;
- 偶数行时,中位数是中间两行LAT_N值的平均值;
- 用CASE WHEN分支处理这两种情况,输出最终结果。
完整SQL代码(MySQL 8.0+ 支持窗口函数版本)
WITH ranked_lat AS ( SELECT LAT_N, -- 按LAT_N排序,给每行分配序号 ROW_NUMBER() OVER (ORDER BY LAT_N) AS row_num, -- 一次性获取总行数 COUNT(*) OVER () AS total_rows FROM station ) SELECT CASE -- 总行数为奇数时,取中间位置的数值 WHEN total_rows % 2 = 1 THEN (SELECT LAT_N FROM ranked_lat WHERE row_num = (total_rows + 1) / 2) -- 总行数为偶数时,取中间两个数的平均值 ELSE (SELECT AVG(LAT_N) FROM ranked_lat WHERE row_num IN (total_rows / 2, total_rows / 2 + 1)) END AS median_lat_n FROM ranked_lat LIMIT 1; -- 只返回一行结果即可
低版本MySQL兼容方案(无CTE支持时)
如果你的MySQL版本低于8.0,不支持WITH语句,可以改用子查询实现:
SELECT CASE WHEN total_rows % 2 = 1 THEN (SELECT LAT_N FROM ( SELECT LAT_N, ROW_NUMBER() OVER (ORDER BY LAT_N) AS row_num FROM station ) AS ranked WHERE row_num = (total_rows + 1) / 2) ELSE (SELECT AVG(LAT_N) FROM ( SELECT LAT_N, ROW_NUMBER() OVER (ORDER BY LAT_N) AS row_num FROM station ) AS ranked WHERE row_num IN (total_rows / 2, total_rows / 2 + 1)) END AS median_lat_n FROM (SELECT COUNT(*) AS total_rows FROM station) AS total;
代码说明
ROW_NUMBER() OVER (ORDER BY LAT_N):给排序后的LAT_N每行分配唯一序号,确保我们能精准定位中间行;COUNT(*) OVER ():一次性获取整个表的总行数,避免重复查询表提升效率;- CASE WHEN分支:根据总行数的奇偶性,自动匹配对应的中位数计算逻辑;
- 子查询/CTE的作用:先完成排序和计数的预处理,再在CASE WHEN中快速定位目标行。
这样就能准确算出LAT_N列的中位数啦~
内容的提问来源于stack exchange,提问作者joey
相关产品推荐
相关产品推荐

