Postgres分区/按值分组

时间:2018-06-21 21:02:45

标签: sql postgresql group-by

我想构建一个查询,该查询不是按值本身对数据进行分组,而是按值在行之间变化这一事实进行分组。我将不胜感激!这是一个示例:

假设我有一个具有以下结构的表:

create table events (
  event_time timestamp, 
  source_id integer references source(id),
  metric integer,
  flagged boolean
);

以及以下示例数据:

source_id | event_time | metric | flagged
-----------------------------------------
1         | 8:00       | 1      | t
1         | 8:10       | 15     | f
1         | 8:20       | 7      | t
1         | 8:30       | 3      | t
1         | 8:40       | 6      | f
1         | 8:50       | 10     | t 
2         | 9:00       | 5      | t

我想查询metric的平均值,以source_id为组的子组,但要根据flagged不变的事实来对这些子组进行分组如果数据是有序的,则从第一行到下一行。也就是说,在上面的示例中,我并不是要group by source_id, flagged,因为这只会为每个source_id提供两个组,而是按时间顺序对连续的行进行分组,其中{{1} }在相邻的行中具有相同的值。也就是说,我想分为以下几组:

flagged
在输出中不需要

group_number | source_id | flagged | avg(metric) ------------------------------------------------ 1 | 1 | t | 1 -- group includes entry for 8:00 only 2 | 1 | f | 15 -- entry for 8:15 only 3 | 1 | t | 5 -- entries on 8:20 & 8:30, (7+3)/2 4 | 1 | f | 6 -- entry for 8:40 only 5 | 1 | t | 10 -- entry for 8:50 only 6 | 2 | t | 5 -- 9:00 from source_id = 2 ,这里只是为了使情况更清楚。此外,我不需要不是group_number的条目-基本上,它们仅用于拆分组。

我试图通过分区以及flaggedranks来做到这一点,但到目前为止没有任何效果。将不胜感激!谢谢。

1 个答案:

答案 0 :(得分:1)

这是一个孤岛问题。一种解决方案是使用行号的差异。

select source_id, flagged, avg(metric)
from (select e.*,
             row_number() over (partition by source_id order by event_time) as seqnum_1,
             row_number() over (partition by source_id, flagged order by event_time) as seqnum_2
      from events e
     ) e
group by source_id, flagged, (seqnum_1 - seqnum_2);

此工作的原因很难解释。我发现,如果运行子查询,您将看到行号之间的差异如何标识具有相同标志的相邻行的组。