PostgreSQL计算一天中小时的平均值和标准差

时间:2016-05-20 04:15:13

标签: postgresql datetime statistics

我有一组带时间戳的事件数据,我想知道这些事件发生的平均值(算术平均值)和标准偏差(以小时为单位)。时间戳以UTC时区为单位,但事件是可能在不同时区发生的用户活动的结果,例如, UTC + 12,我不知道哪个。

这似乎很容易做到,但由于24小时的周期性,它并不明显。 (例如23和0小时在实践中靠得很近,但不是数学上的。)

以下是一个例子:

考虑到这些时间:3, 4, 3, 0, 21, 23, 4,平均值看起来是8.3,标准偏差(人口)是8.8。但是,如果这些事件发生在UTC + 12中,那将是不正确的,因为"真实"小时为15, 16, 15, 12, 9, 11, 16,平均值为13.4,标准开发(pop)2.6。

计算正确均值的最佳方法是什么(UTC为13.4)和stddev(pop)(2.6)?

示例数据(events表):

id |     timestamp
---+--------------------
1  | 2016-05-20 03:00:00
2  | 2016-05-20 04:00:00
3  | 2016-05-20 03:00:00
4  | 2016-05-20 00:00:00
5  | 2016-05-20 21:00:00
6  | 2016-05-20 23:00:00
7  | 2016-05-20 04:00:00

我现在正在使用的PostgreSQL查询如下:

SELECT CAST(avg(extract(epoch FROM timestamp::TIME)) AS dec(18, 10)), 
       CAST(stddev_pop(extract(epoch FROM timestamp::TIME)) AS dec(18, 10)) 
FROM   events

目前的结果:

      Mean       |      Stddev   
-----------------+-----------------
29828.5714285714 | 31602.4282198023

(这是在几秒钟内,这个小时是平均8.3和std dev 8.8。)

预期结果是~13.4,标准差~2.6。

1 个答案:

答案 0 :(得分:1)

您可以使用AT TIME ZONE转换时区。

SET TIME ZONE 'UTC';

WITH
test(id, dummy_time) as
(
values
(1, TIMESTAMP '2016-05-20 03:00:00'),
(2, TIMESTAMP '2016-05-20 04:00:00'),
(3, TIMESTAMP '2016-05-20 03:00:00'),
(4, TIMESTAMP '2016-05-20 00:00:00'),
(5, TIMESTAMP '2016-05-20 21:00:00'),
(6, TIMESTAMP '2016-05-20 23:00:00'),
(7, TIMESTAMP '2016-05-20 04:00:00')
)

SELECT      avg(date_part('HOUR', dummy_time AT TIME ZONE 'UTC+12')) as AVERAGE_HOUR,
            stddev_pop(date_part('HOUR', dummy_time AT TIME ZONE 'UTC+12')) as STDEV_HOUR

FROM        test

这给出了你想要的13.4均值和2.6 stdev。