У меня есть упорядоченные по времени данные (например, транзакции по счету), и для каждой учетной записи у меня есть дата и индикатор того, превышает ли транзакция определенный порог (например, 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;