如何按非唯一值对以下行进行分组

How to group following rows by not unique value

我有这样的数据:

table1
_____________
id way time
1  1   00:01
2  1   00:02
3  2   00:03
4  2   00:04
5  2   00:05
6  3   00:06
7  3   00:07
8  1   00:08
9  1   00:09

我想知道我在哪个时间间隔走的是哪条路:

desired output
_________________
id  way from   to    
1   1   00:01  00:02
3   2   00:03  00:05
6   3   00:06  00:07
8   1   00:08  00:09

我尝试使用 window 函数:

SELECT DISTINCT
  first_value(id) OVER w AS id, 
  first_value(way) OVER w as way,
  first_value(time) OVER w as from,
  last_value(time) OVER w as to
FROM table1
WINDOW w AS (
  PARTITION BY way ORDER BY ID
  range between unbounded preceding and unbounded following);

我得到的是:

ID  way from   to    
 1   1  00:01  00:09
 3   2  00:03  00:05
 6   3  00:06  00:07

这是不正确的,因为在第 1 条路上我不是从 00:01 到 00:09。 是否可以按顺序进行分区,意味着只对以下相等的属性进行分组?

我想你想要这样的东西:

select min(id), way, 
       min(time), max(time)
from (
select id, way, time,
       ROW_NUMBER() OVER (ORDER BY id) - 
       ROW_NUMBER() OVER (PARTITION BY way ORDER BY time) AS grp
from table1 ) t
group by way, grp

grp 标识 'islands' 个 连续 way 个值。在外部查询中使用此计算字段,我们可以获得 startendway 间隔使用 MINMAX 分别聚合函数。

Demo here

如果您的情况像示例值所建议的那样简单, 就可以很好地发挥作用。

然而,通常情况并非如此。如果 id 列是 serial,则不能依赖具有较早 time 的行也具有较小 id.
的假设 此外,time 值(或你可能拥有的 timestamp 值)很容易重复,你需要使排序顺序明确。

假设两者都可能发生,并且您希望每个时间片中最早 time 的行中的 id(实际上,最小 id最早时间,可能有联系),这个查询将正确处理这种情况:

SELECT *
FROM  (
   SELECT DISTINCT ON (way, grp)
          id, way, time AS time_from
        , max(time) OVER (PARTITION BY way, grp) AS time_to
   FROM (
      SELECT *
           , row_number() OVER (ORDER BY time, id)  -- id as tie breaker
           - row_number() OVER (PARTITION BY way ORDER BY time, id) AS grp
      FROM   table1
      ) t
   ORDER  BY way, grp, time, id
   ) sub
ORDER  BY time_from, id;
  • ORDER BY time, id 不含糊。假设时间 不是 唯一,添加(假设唯一)id 以避免任意结果 - 这可能会以偷偷摸摸的方式在查询之间改变。

  • max(time) OVER (PARTITION BY way, grp):没有ORDER BY,window帧跨越PARTITION的所有行,所以我们得到每个时间片的绝对最大值。

  • 外部查询层只需要在结果中生成所需的排序顺序,因为我们通过使用 sub 绑定到子查询 sub 中的不同 ORDER BY =26=]。详情:

    • Select first row in each GROUP BY group?

SQL Fiddle 演示用例。

如果您希望优化性能,在这种情况下,plpgsql 函数可能会更快。密切相关的答案:

  • Group by repeating attribute

另外:不要使用基本类型名称 time 作为标识符(也是 reserved word in standard SQL)。