SQL Server无MEDIAN函数时,如何正确计算列中位数并保留4位小数?
解决SQL Server中位数计算并保留4位小数的问题
修正你的第一种写法
你的第一个语句结果多了两位末尾0,是因为最终除法运算后的数值精度未做限制,只需在最外层对结果做一次类型转换或小数位数保留即可:
SELECT CAST( ( (SELECT CAST(ROUND(MAX(LAT_N), 4) AS DECIMAL(8, 4)) FROM (SELECT TOP 50 PERCENT LAT_N FROM STATION ORDER BY LAT_N ASC) AS Bottom1) + (SELECT CAST(ROUND(MIN(LAT_N), 4) AS DECIMAL(8, 4)) FROM (SELECT TOP 50 PERCENT LAT_N FROM STATION ORDER BY LAT_N DESC) AS Top1) ) / 2 AS DECIMAL(8,4) );
或者用ROUND直接控制小数位数:
SELECT ROUND( ( (SELECT CAST(ROUND(MAX(LAT_N), 4) AS DECIMAL(8, 4)) FROM (SELECT TOP 50 PERCENT LAT_N FROM STATION ORDER BY LAT_N ASC) AS Bottom1) + (SELECT CAST(ROUND(MIN(LAT_N), 4) AS DECIMAL(8, 4)) FROM (SELECT TOP 50 PERCENT LAT_N FROM STATION ORDER BY LAT_N DESC) AS Top1) ) / 2, 4 );
修正你的第二种写法
第二种写法的核心问题是提前对LAT_N做了/2操作,导致精度丢失,完全没必要这么做。直接去掉子查询里的(LAT_N / 2),回到第一种写法的结构,再按上面的方式处理最终结果的小数位数即可。
更可靠的替代方案
方案1:使用PERCENTILE_CONT(SQL Server 2012+)
SQL Server 2012及以上版本支持PERCENTILE_CONT函数,可直接计算连续分布的中位数,语法简洁且准确:
SELECT CAST(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY LAT_N) OVER () AS DECIMAL(8,4)) AS Median_LAT_N FROM STATION GROUP BY (SELECT NULL); -- 确保仅返回一行结果
该函数会自动处理奇数/偶数行数的中位数计算逻辑,无需手动拆分前后50%数据。
方案2:使用ROW_NUMBER(兼容旧版本SQL Server)
如果你的SQL Server版本低于2012,可借助行号实现中位数计算:
WITH RankedData AS ( SELECT LAT_N, ROW_NUMBER() OVER (ORDER BY LAT_N) AS RowNum, COUNT(*) OVER () AS TotalRows FROM STATION ) SELECT CAST(AVG(LAT_N) AS DECIMAL(8,4)) AS Median_LAT_N FROM RankedData WHERE RowNum IN ((TotalRows + 1)/2, (TotalRows + 2)/2);
通过CTE给每行数据编号,根据总行数的奇偶性,取中间1行或2行的平均值,最终转换为4位小数,避免精度丢失。
内容的提问来源于stack exchange,提问作者Ineffable21
相关产品推荐
相关产品推荐

