Определите группы последовательных равных значений в упорядоченном наборе данных - PullRequest
0 голосов
/ 07 декабря 2018

Я пытаюсь получить вывод, как показано ниже.Проблема в том, что я не могу сделать first_value или RANK, потому что, когда я делю по событиям и по времени, они не разбиваются в этом порядке.Мне нужно, чтобы они сначала заказывали по времени, а потом каждый раз делали.

enter image description here

1 Ответ

0 голосов
/ 07 декабря 2018

Одно из известных решений

Используйте lag(), чтобы пометить строки, когда event изменяется, и кумулятивно 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)'
);

Протестировать его в rextester.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...