2012-10-04 65 views
2

我想繪製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()它可以減少時間戳到一定程度的分辨率到the docs):

... 
second 
minute 
hour 
day 
week 
... 

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

這樣,我可以爲以下間隔尺寸(以及一些更大/更小的尺寸)這樣做


有沒有一種方法可以在其他時間間隔內實現這一點,例如3小時6小時?

回答

5

考慮這個演示帶來時間戳下降到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 

關鍵是要提取Unix紀元像@邁克爾已經發布。整數除法將它們放在所選分辨率的桶中,因爲小數位被截斷。

我除以900,因爲15分鐘= 900秒。

乘以相同數字即可得到lower_bound。 使用to_timestamp()將unix時期轉換回時間戳。

這對於可以在小數系統中沒有小數位的情況下表示的間隔非常有用。爲了更多的多功能性使用經常被忽視的功能width_bucket()就像我在這個recent, closely related answer中演示的那樣。更多解釋,鏈接和一個sqlfiddle演示在那裏。

0

可以轉換成的紀元以來的秒數,去了3 * 3600的整數除法,6 * 3600等