考虑这个演示,以将时间戳降低到 15 分钟的分辨率并汇总产生的欺骗:
WITH tbl(id, ts) AS ( VALUES
(1::int, '2012-10-04 00:00:00'::timestamp)
,(2, '2012-10-04 18:23:01')
,(3, '2012-10-04 18:30:00')
,(4, '2012-10-04 18:52:33')
,(5, '2012-10-04 18:55:01')
,(6, '2012-10-04 18:59:59')
,(7, '2012-10-05 11:01:01')
)
SELECT to_timestamp((extract(epoch FROM ts)::bigint / 900)*900)::timestamp
AS lower_bound
, to_timestamp(avg(extract(epoch FROM ts)))::timestamp AS avg_ts
, count(*) AS ct
FROM tbl
GROUP BY 1
ORDER BY 1;
结果:
lower_bound | avg_ts | ct
---------------------+---------------------+----
2012-10-04 00:00:00 | 2012-10-04 00:00:00 | 1
2012-10-04 18:15:00 | 2012-10-04 18:23:01 | 1
2012-10-04 18:30:00 | 2012-10-04 18:30:00 | 1
2012-10-04 18:45:00 | 2012-10-04 18:55:51 | 3
2012-10-05 11:00:00 | 2012-10-05 11:01:01 | 1
诀窍是提取像@Michael 已经发布的unix 纪元。整数除法将它们集中在所选分辨率的桶中,因为小数位被截断。
我除以 900,因为 15 分钟 = 900 秒。
乘以相同的数字得到结果lower_bound
。将 unix 纪元转换回带有to_timestamp()
.
这对于可以在十进制系统中没有小数位表示的间隔非常有用。要获得更多功能,请使用width_bucket()
我在最近密切相关的答案中演示的经常被忽视的功能。那里有更多解释、链接和 sqlfiddle 演示。