3

我想my_values在时间轴上以比数据库中更低的分辨率进行绘图。我使用类似下面的 SQL 来获取每个时间间隔(例如,一个小时)的平均值:

SELECT DATE_TRUNC('hour', my_timestamps) AS my_time_lowres
     , AVG(my_values) 
FROM my_table 
GROUP BY my_time_lowres

使用date_trunc()它可以在一定程度上降低时间戳的分辨率(根据文档):

select date_trunc('hour', timestamp '2001-02-16 20:38:40') 
-- the output is: 2001-02-16 20:00:00

这样,我可以对以下间隔大小(以及一些更大/更小的大小)执行此操作:

...
second
minute
hour
day
week
...

有没有办法在其他时间间隔内实现这一点,例如 3 小时、6 小时?

4

2 回答 2

6

考虑这个演示,以将时间戳降低到 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 演示。

于 2012-10-04T16:34:03.933 回答
0

您可以转换为自纪元以来的秒数,然后将整数除以 3*3600、6*3600 等。

于 2012-10-04T14:57:28.610 回答