MySQL中时间类型列的精确中位数获取及结果取整问题
问题分析与解决方案
为什么结果被取整?
你的查询结果被取整的核心原因是时间转换过程中丢失了小数精度:
TIME_TO_SEC(ride_time)会将TIME类型值转换为整数秒数,直接丢弃TIME字段中存储的毫秒/微秒部分。- 当你对这些整数秒取平均值后,即使结果带有小数(比如8.5秒),
SEC_TO_TIME()函数会自动截断小数部分,只保留整数秒,最终呈现为整分钟的时间值(如00:08:00.0000)。
如何获取精确的中位数?
方法1:保留微秒精度重新计算
将TIME类型转换为包含微秒的精确数值,计算平均后再转回TIME类型,完整保留小数精度:
WITH RankedRides AS ( SELECT ride_time, ROW_NUMBER() OVER (ORDER BY ride_time) AS row_num, COUNT(*) OVER () AS total_rows FROM q4_2022_data ) SELECT SEC_TO_TIME( AVG( TIME_TO_SEC(ride_time) + MICROSECOND(ride_time) / 1000000 ) ) AS median_ride_time FROM RankedRides WHERE row_num BETWEEN (total_rows DIV 2) + 1 AND (total_rows DIV 2) + 2;
这里通过MICROSECOND(ride_time)/1000000把微秒转换为秒的小数部分,和整数秒合并后计算平均值,再转回TIME类型,就能保留完整的精度。
方法2:使用PERCENTILE_CONT函数(MySQL 8.0+)
如果你使用的是MySQL 8.0及以上版本,更推荐用PERCENTILE_CONT(连续百分位数函数)直接计算,它会返回精确的中位数(偶数条记录时自动取中间两个值的平均),无需手动排序分组:
SELECT SEC_TO_TIME( PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY TIME_TO_SEC(ride_time) + MICROSECOND(ride_time)/1000000 ) ) AS median_ride_time FROM q4_2022_data;
补充:你之前尝试的
PERCENTILE_DISC是离散百分位数函数,它只会返回表中实际存在的某条记录的ride_time值,不会计算平均值,这也是它没达到你预期的原因。
内容的提问来源于stack exchange,提问作者teghs
相关产品推荐
相关产品推荐

