PostgreSQL求和时间跨度时为何未完全转换单位?
为什么PostgreSQL求和时间间隔时不把小时完全转换为天?
问题背景
我创建了如下结构的room_server_metrics表:
create table room_server_metrics ( namespace varchar(36) not null, session_id varchar(36) not null, primary key (namespace, session_id), created_at timestamptz not null default now(), updated_at timestamptz not null default now(), );
当统计所有会话总时长时,执行以下查询得到结果:
database=> select sum(updated_at - created_at) as total_time from room_server_metrics; total_time ---------------------------- 94 days 60951:01:56.381483
计算后发现94天加60951小时约等于2633天,但直接以秒为单位输出时:
database=> select extract(epoch from sum(updated_at - created_at)) as total_time from room_server_metrics; total_time ---------------------------- 227546617.181704
该秒数同样约等于2633天,疑惑为何第一个查询未将超过94天的小时数完全转换为天单位?
原因解释
这是PostgreSQL对interval类型求和的默认行为:它会分别累加时间间隔的各个字段(天、小时、分钟、秒等),而不会自动将低位字段(如小时)进位到高位字段(如天)。
比如两个会话时长分别是1 day 25:00:00和2 days 23:00:00,求和后会直接得到3 days 48:00:00,而非自动把48小时转换成2天得到5 days 00:00:00。你查询里的60951小时就是所有会话的小时字段直接相加的结果,没有做进位处理。
解决方法
如果想要得到完全进位后的规整时间格式,可以使用PostgreSQL的justify_interval函数,它会自动将所有时间字段进位到合理的单位:
select justify_interval(sum(updated_at - created_at)) as total_time from room_server_metrics;
执行后,60951小时会被转换成2539 days 15:00:00,加上原有的94天,最终结果会显示为2633 days 15:01:56.381483,和秒数计算的结果一致。
另外也可以先转成秒再计算成天:
select sum(extract(epoch from (updated_at - created_at))) / 86400 as total_days from room_server_metrics;
内容的提问来源于stack exchange,提问作者mxweas
相关产品推荐
相关产品推荐

