在psql中聚合时间序列
Aggregating time sequences in psql
我是 psql window 函数的新手,想对 test_table
执行查询,以找出每个 inactive 中断实例mobile_id
、country
和 brand
以及中断持续时间(以秒为单位)。
每次中断都应视为一个单独的事件,换句话说,按时间排序时,active
行的出现应重置计数。
如果只有一个独立的 "inactive" 记录,则不会有 difftime
,这些情况应分配默认值 60。
例如:
> test_table
mobile_id state country brand time
1 1a inactive dk nokia 2018-08-09 19:01:53
2 1a inactive dk nokia 2018-08-09 18:51:39
3 1a active dk nokia 2018-08-09 18:42:10
4 1a inactive dk nokia 2018-08-09 18:31:23
5 1a inactive dk nokia 2018-08-09 18:21:27
6 2a active dk apple 2018-08-09 18:12:08
7 2a active dk apple 2018-08-09 18:01:45
8 2a active dk apple 2018-08-09 17:51:29
9 2a active dk apple 2018-08-09 17:41:27
10 2a inactive dk apple 2018-08-09 17:31:32
11 3a active de nokia 2018-08-09 17:21:34
12 3a active de nokia 2018-08-09 17:11:48
13 3a active de nokia 2018-08-09 17:01:46
14 3a active de nokia 2018-08-09 16:51:31
15 3a active de nokia 2018-08-09 16:41:34
查询 test_table
会产生如下结果:
> outages
id country brand diff_time
1 1 dk nokia 614
2 2 dk nokia 596
3 3 dk apple 60
如何构建这样的查询?
您可以通过计算之前的活动总和来识别非活动组。剩下的基本上就是聚合了:
select mobile_id, brand, country,
least(extract(epoch from max(time) - min(time)), 60) as diff
from (select t.*,
count(*) filter (where state = 'active') over (partition by mobile_id, brand, country order by time) as grp
from t
) t
group by mobile_id, brand, country, grp;
我是 psql window 函数的新手,想对 test_table
执行查询,以找出每个 inactive 中断实例mobile_id
、country
和 brand
以及中断持续时间(以秒为单位)。
每次中断都应视为一个单独的事件,换句话说,按时间排序时,active
行的出现应重置计数。
如果只有一个独立的 "inactive" 记录,则不会有 difftime
,这些情况应分配默认值 60。
例如:
> test_table
mobile_id state country brand time
1 1a inactive dk nokia 2018-08-09 19:01:53
2 1a inactive dk nokia 2018-08-09 18:51:39
3 1a active dk nokia 2018-08-09 18:42:10
4 1a inactive dk nokia 2018-08-09 18:31:23
5 1a inactive dk nokia 2018-08-09 18:21:27
6 2a active dk apple 2018-08-09 18:12:08
7 2a active dk apple 2018-08-09 18:01:45
8 2a active dk apple 2018-08-09 17:51:29
9 2a active dk apple 2018-08-09 17:41:27
10 2a inactive dk apple 2018-08-09 17:31:32
11 3a active de nokia 2018-08-09 17:21:34
12 3a active de nokia 2018-08-09 17:11:48
13 3a active de nokia 2018-08-09 17:01:46
14 3a active de nokia 2018-08-09 16:51:31
15 3a active de nokia 2018-08-09 16:41:34
查询 test_table
会产生如下结果:
> outages
id country brand diff_time
1 1 dk nokia 614
2 2 dk nokia 596
3 3 dk apple 60
如何构建这样的查询?
您可以通过计算之前的活动总和来识别非活动组。剩下的基本上就是聚合了:
select mobile_id, brand, country,
least(extract(epoch from max(time) - min(time)), 60) as diff
from (select t.*,
count(*) filter (where state = 'active') over (partition by mobile_id, brand, country order by time) as grp
from t
) t
group by mobile_id, brand, country, grp;