【问题标题】:Designate groups of consecutive equal values in an ordered dataset在有序数据集中指定连续相等值的组
【发布时间】:2018-12-06 23:06:31
【问题描述】:

我正在尝试使输出如下所示。问题是我不能做 first_value 或 RANK 因为当我按事件分区和按时间排序时,它不会按那个顺序分解它们。我需要他们先按时间排序,然后每次分区。

【问题讨论】:

  • 请显示示例输入、示例输出以及您尝试解决问题的查询。
  • 所以我会有行事件和时间,需要弄清楚如何获得所需的行号。我试过: SELECT event, time, ROW_NUMBER () OVER( PARITITON BY event ORDER BY time ASC) as rn FROM TABLE 但这只是将所有事件按顺序排列,没有办法让它成为唯一的。跨度>

标签: postgresql aggregate-functions window-functions gaps-and-islands


【解决方案1】:

已知解决方案之一

event发生变化时使用lag()标记行,使用累积sum()指定组,例如:

with my_table(event, time) as (
values 
    ('A', '12:01'),
    ('A', '12:02'),
    ('B', '12:03'),
    ('A', '12:04'),
    ('A', '12:05'),
    ('B', '12:06'),
    ('B', '12:07'),
    ('A', '12:08')
)

select 
    event, 
    time, 
    sum(change) over (order by time) as "desired row number"
from (
    select 
        event, 
        time, 
        (event is distinct from lag(event) over (order by time))::int as change
    from my_table
    ) s

 event | time  | desired row number 
-------+-------+--------------------
 A     | 12:01 |                  1
 A     | 12:02 |                  1
 B     | 12:03 |                  2
 A     | 12:04 |                  3
 A     | 12:05 |                  3
 B     | 12:06 |                  4
 B     | 12:07 |                  4
 A     | 12:08 |                  5
(8 rows)

自定义聚合

如果有这个功能就好了:

select *, group_number(event) over (order by time)
from my_table;

这可以通过自定义聚合来完成:

create type group_number_internal as (number int, lag text);

create or replace function group_number_transition(group_number_internal, anyelement)
returns group_number_internal language sql strict as $$
    select 
        case 
            when $2::text is distinct from $1.lag then $1.number+ 1 
            else $1.number 
        end, 
        $2::text
$$;

create or replace function group_number_final(group_number_internal)
returns int language sql as $$
    select $1.number
$$;

create aggregate group_number(anyelement) (
    sfunc = group_number_transition,
    stype = group_number_internal,
    finalfunc = group_number_final,
    initcond = '(0, null)'
);

Test it in rextester.

【讨论】:

    猜你喜欢
    • 2017-05-15
    • 1970-01-01
    • 2015-06-20
    • 2021-04-29
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    • 2020-09-13
    • 1970-01-01
    相关资源
    最近更新 更多