Amazon Redshift中VARCHAR格式时长字段的总时长计算SQL需求问询
计算Amazon Redshift中超过24小时的VARCHAR时长总和
没问题!针对你这种存储为VARCHAR类型、格式为小时:分钟:秒.微秒(部分数据无秒后微段)的时长字段求和需求,我整理了一套在Redshift中可行的SQL方案,既能处理超过24小时的情况,还能完整保留微秒精度。
核心思路
我们需要分两步实现:
- 将每个时长字符串转换为总微秒数(数值类型方便求和计算)
- 将求和后的总微秒数转换回
小时:分钟:秒.微秒的格式
完整SQL语句
WITH duration_micro AS ( SELECT -- 拆分时长字符串,兼容有无微秒的两种格式 CASE WHEN POSITION('.' IN duration) > 0 THEN -- 有微秒的情况:计算总微秒数 CAST(split_part(duration, ':', 1) AS BIGINT) * 3600 * 1000000 + CAST(split_part(duration, ':', 2) AS BIGINT) * 60 * 1000000 + CAST(split_part(split_part(duration, '.', 1), ':', 3) AS BIGINT) * 1000000 + CAST(split_part(duration, '.', 2) AS BIGINT) ELSE -- 无微秒的情况:补000000后计算总微秒数 CAST(split_part(duration, ':', 1) AS BIGINT) * 3600 * 1000000 + CAST(split_part(duration, ':', 2) AS BIGINT) * 60 * 1000000 + CAST(split_part(duration, ':', 3) AS BIGINT) * 1000000 + 0 END AS total_microseconds FROM your_table_name -- 替换为你的实际表名 ), total_sum AS ( SELECT SUM(total_microseconds) AS total_micro FROM duration_micro ) SELECT -- 总小时数(直接显示,支持超过24小时) CAST(total_micro / (3600 * 1000000) AS VARCHAR) || ':' || -- 分钟数(补零到两位) LPAD(CAST((total_micro % (3600 * 1000000)) / (60 * 1000000) AS VARCHAR), 2, '0') || ':' || -- 秒数(补零到两位) LPAD(CAST((total_micro % (60 * 1000000)) / 1000000 AS VARCHAR), 2, '0') || '.' || -- 微秒数(补零到六位) LPAD(CAST(total_micro % 1000000 AS VARCHAR), 6, '0') AS total_duration FROM total_sum;
关键细节说明
- 兼容两种格式:用
POSITION判断是否包含小数点,分别处理有/无微秒的时长数据,避免计算错误。 - 避免数值溢出:使用
BIGINT类型存储总微秒数,即使是多天的时长也不会出现溢出问题。 - 格式规范统一:通过
LPAD函数确保分钟、秒为两位,微秒为六位,和原始数据格式保持一致。 - 支持超24小时:总小时数直接计算不做模24处理,能正确显示36小时这类跨天的结果。
示例数据验证
把你给出的8条示例数据代入计算,最终得到的总时长为36:18:28.536000,和你提到的约36小时18分28秒完全匹配。
内容的提问来源于stack exchange,提问作者As R




