【发布时间】:2018-09-20 06:29:52
【问题描述】:
我有一个大型 Postgres 表 test,我想从中提取 连续 序列的 no_signal 每个 mobile_id 状态,或者换句话说,单个移动设备运行的时间长度中止服务。
在真实表中,记录没有排序,我认为这意味着除了窗口函数之外,还必须包含 PARTITION OVER (time, mobile_id) 语句。任何关于如何为单个连续序列创建一个组,然后为每个组取最小值和最大值的建议将不胜感激。
-- CREATE TABLE test (mobile_id int, state varchar, time timestamp, region varchar)
INSERT INTO test (mobile_id, state, time, region ) VALUES
(1, 'active', TIMESTAMP '2018-08-09 15:00:00', 'EU'),
(1, 'active', TIMESTAMP '2018-08-09 16:00:00', 'EU'),
(1, 'no_signal', TIMESTAMP '2018-08-09 17:00:00', 'EU'),
(1, 'no_signal', TIMESTAMP '2018-08-09 18:00:00', 'EU'),
(1, 'no_signal', TIMESTAMP '2018-08-09 19:00:00', 'EU'),
(1, 'active', TIMESTAMP '2018-08-09 20:00:00', 'EU'),
(1, 'inactive', TIMESTAMP '2018-08-09 21:00:00', 'EU'),
(1, 'active', TIMESTAMP '2018-08-09 22:00:00', 'EU'),
(1, 'active', TIMESTAMP '2018-08-09 23:00:00', 'EU'),
(2, 'active', TIMESTAMP '2018-08-10 00:00:00', 'EU'),
(2, 'no_signal', TIMESTAMP '2018-08-10 01:00:00', 'EU'),
(2, 'active', TIMESTAMP '2018-08-10 02:00:00', 'EU'),
(2, 'no_signal', TIMESTAMP '2018-08-10 03:00:00', 'EU'),
(2, 'no_signal', TIMESTAMP '2018-08-10 04:00:00', 'EU'),
(2, 'no_signal', TIMESTAMP '2018-08-10 05:00:00', 'EU'),
(2, 'no_signal', TIMESTAMP '2018-08-10 06:00:00', 'EU'),
(3, 'active', TIMESTAMP '2018-08-10 07:00:00', 'SA'),
(3, 'active', TIMESTAMP '2018-08-10 08:00:00', 'SA'),
(3, 'no_signal', TIMESTAMP '2018-08-10 09:00:00', 'SA'),
(3, 'no_signal', TIMESTAMP '2018-08-10 10:00:00', 'SA'),
(3, 'inactive', TIMESTAMP '2018-08-10 11:00:00', 'SA'),
(3, 'inactive', TIMESTAMP '2018-08-10 12:00:00', 'SA'),
(3, 'no_signal', TIMESTAMP '2018-08-10 13:00:00', 'SA')
我的目标是这样的输出:
mobile_id start_time end_time diff_time region
1 2018-08-09 17:00:00 2018-08-09 19:00:00 120 EU
2 2018-08-10 01:00:00 2018-08-10 01:00:00 0 EU
2 2018-08-10 03:00:00 2018-08-10 06:00:00 180 EU
3 2018-08-10 09:00:00 2018-08-10 10:00:00 60 SA
3 2018-08-10 13:00:00 2018-08-10 13:00:00 0 SA
由于未正确创建组,因此以下代码不会产生所需的结果:
select mobile_id, region,
least(extract(epoch from max(time) - min(time)), 0) as diff
from (select t.*,
count(*) filter (where state = 'no_signal) over (partition by mobile_id, region order by time) as grp
from t
) t
group by mobile_id, region, grp;
【问题讨论】:
标签: sql postgresql window-functions