对重复的列进行分组

问题描述 投票:0回答:3

我很难用语言表达这个问题,这可能就是为什么我找不到例子,所以这就是我想做的。

我有一张这样的桌子

    | counter|      timestamp      |
    |   1    | 2018-01-01T11:11:01 |
    |   1    | 2018-01-01T11:11:02 |
    |   1    | 2018-01-01T11:11:03 |
    |   2    | 2018-01-01T11:11:04 |
    |   2    | 2018-01-01T11:11:05 |
    |   3    | 2018-01-01T11:11:06 |
    |   3    | 2018-01-01T11:11:07 |
    |   1    | 2018-01-01T11:11:08 |
    |   1    | 2018-01-01T11:11:09 |
    |   1    | 2018-01-01T11:11:10 |

我想做的是按每组计数器进行分组,所以如果我执行像

这样的查询
SELECT counter, MAX(timestamp) as st, MIN(timestamp) as et 
FROM table 
GROUP BY counter;

结果将是

    | counter |          st         |         et          |
    |   1     | 2018-01-01T11:11:01 | 2018-01-01T11:11:03 |
    |   2     | 2018-01-01T11:11:04 | 2018-01-01T11:11:05 |
    |   3     | 2018-01-01T11:11:06 | 2018-01-01T11:11:07 |
    |   1     | 2018-01-01T11:11:08 | 2018-01-01T11:11:10 |

而不是实际发生的事情

    | counter |          st         |         et          |
    |   1     | 2018-01-01T11:11:01 | 2018-01-01T11:11:10 |
    |   2     | 2018-01-01T11:11:04 | 2018-01-01T11:11:05 |
    |   3     | 2018-01-01T11:11:06 | 2018-01-01T11:11:07 |

所以我想要一些在没有嵌套查询的情况下理想地组合分组依据和分区的内容

sql postgresql aggregate-functions window-functions
3个回答
4
投票

您必须指定具有相同计数器重复值的组。这可以使用两个窗口函数

lag()
和累积
sum()
来完成:

select counter, min(timestamp) as st, max(timestamp) as et
from (
    select counter, timestamp, sum(grp) over w as grp
    from (
        select *, (lag(counter, 1, 0) over w <> counter)::int as grp
        from my_table
        window w as (order by timestamp)
        ) s
    window w as (order by timestamp)
    ) s
group by counter, grp
order by st

DbFiddle。


1
投票

你应该计算一个新的组:

create table tbl(counter int, ts timestamp);
insert into tbl values
    (1, '2018-01-01T11:11:01'),
    (1, '2018-01-01T11:11:02'),
    (1, '2018-01-01T11:11:03'),
    (2, '2018-01-01T11:11:04'),
    (2, '2018-01-01T11:11:05'),
    (3, '2018-01-01T11:11:06'),
    (3, '2018-01-01T11:11:07'),
    (1, '2018-01-01T11:11:08'),
    (1, '2018-01-01T11:11:09'),
    (1, '2018-01-01T11:11:10');
✓

10 行受影响
select min(counter) as counter, min(ts) as st, max(ts) as et
from
(
    select counter, ts, sum(rst) over (order by ts) as grp
    from 
         (
         select counter, ts,
                case when coalesce(lag(counter) over (order by ts), -1) <> counter then 1 end rst
         from   tbl
         ) t1
) t2
group by grp
柜台 |圣 |等
------: | :------------------ | :------------------
      3 | 2018-01-01 11:11:06 | 2018-01-01 11:11:07
      1 | 2018-01-01 11:11:08 | 2018-01-01 11:11:10
      2 | 2018-01-01 11:11:04 | 2018-01-01 11:11:05
      1 | 2018-01-01 11:11:01 | 2018-01-01 11:11:03

db<>小提琴这里


1
投票

您可以使用排名功能

select counter, min(timestamp) st, max(timestamp) et
from (select *, 
               row_number() over (order by timestamp) Seq1,
               row_number() over (partition by counter order by timestamp) Seq2 
      from table 
     ) t
group by counter, (Seq1-Seq2);

这将使用两个排名函数 (

Seq1-Seq2
) 的差异并在
GROUP BY
子句中使用它们。

© www.soinside.com 2019 - 2024. All rights reserved.