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

У меня есть упорядоченные по времени данные (например, транзакции по счету), и для каждой учетной записи у меня есть дата и индикатор того, превышает ли транзакция определенный порог (например, 100 долларов США).Я хотел бы рассчитать для каждого аккаунта максимальное количество последовательных транзакций со значением выше $ 100.

У меня есть решение, но для преобразования данных и окончательной агрегации требуется три шага.Есть ли более разумный способ, как подойти к этому?Для примера данных ниже число, которое я ищу:

--seq 1 --> result 3
--seq 2 --> result 1

/*
select * from tmp_is_something;
drop table tmp_is_something;
-- seq - order of the transaction (1 = most recent)
-- part - account id
-- expr - 1 = transaction > $100, 0 = transaction <= $100
create table tmp_is_something (seq number, part number, expr number);
insert into tmp_is_something values(1,1,1);
insert into tmp_is_something values(2,1,1);
insert into tmp_is_something values(3,1,0);
insert into tmp_is_something values(4,1,0);
insert into tmp_is_something values(5,1,0);
insert into tmp_is_something values(6,1,1);
insert into tmp_is_something values(7,1,1);
insert into tmp_is_something values(8,1,0);
insert into tmp_is_something values(9,1,1);
insert into tmp_is_something values(10,1,1);
insert into tmp_is_something values(11,1,1);
insert into tmp_is_something values(12,1,0);
insert into tmp_is_something values(1,2,1);
insert into tmp_is_something values(2,2,0);
insert into tmp_is_something values(3,2,1);
commit;
*/

Запрос:

with t as (
  select 
    seq, 
    part, 
    expr, 
    count(*) over(partition by part) as cnt,
    case when expr <> coalesce(lag(expr, 1) over(partition by part order by seq), expr) then 1 else 0 end as change_to_prev,  
    row_number() over(partition by part order by seq) as rn
  from tmp_is_something
) 

, u  as (
  select 
    seq, part, expr, cnt, rn, change_to_prev, 
    sum(change_to_prev) 
         over (partition by part order by seq rows between unbounded preceding and current row) + 1 as flip_sequence
  from t 
)

, v as (
  select 
    part, 
    flip_sequence, 
    count(*) cnt, 
    max(expr) expr, 
    max(rn) last_rn, 
    max(rn) - count(*) rn_diff 
  from 
    u
  group by 
    part, 
    flip_sequence
)

select 
  part,
  listagg( expr || '-' || cnt || '; ') within group (order by flip_sequence) as seq_str,
  max(expr * cnt) max_con_is
from v
group by part;

1 Ответ

0 голосов
/ 26 сентября 2018

Используйте аналитический sum() дважды, чтобы создать столбец группировки на основе непрерывных данных, затем используйте этот столбец для дальнейшего анализа:

демо

select part, max(cnt) cnt
  from (select part, grp, count(1) cnt 
          from (select tmp.*, 
                       sum(1) over (partition by part order by seq) 
                       - sum(expr) over (partition by part order by seq) grp
                  from tmp)
          where expr = 1 group by part, grp)
  group by part
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...