Ok, isso vai ser difícil de explicar.
Em cada data para cada status, você deve contar dois valores:
- O número de clientes que começam com esse status.
- O número de clientes que saem com esse status.
O primeiro valor é fácil. É apenas a agregação das transações pela data e pelo status.
O segundo valor é quase tão fácil. Você obtém o anterior código de status e conte o número de vezes que esse código de status "sai" naquela data.
Então, a chave é a soma cumulativa do primeiro valor menos a soma cumulativa do segundo valor.
Admito livremente que o código a seguir não foi testado (se você tivesse um SQL Fiddle, ficaria feliz em testá-lo). Mas é assim que a consulta resultante se parece:
select status_dte, status_cd,
(sum(inc_cnt) over (partition by status_cd order by status_dt) -
sum(dec_cnt) over (partition by status_cd order by status_dt)
) as dateamount
from ((select t.status_dt, t.status_cd, count(*) as inc_cnt, 0 as dec_cnt
from transactions t
group by t.status_dt, t.status_cd
) union all
(select t.status_dt, prev_status_cd, 0, count(*)
from (select t.*
lag(t.status_cd) over (partition by t.account_id order by status_dt) as prev_status_cd
from transactions t
) t
where prev_status_cd is null
group by t.status_dt, prev_status_cd
)
) t;
Se você tiver datas em que não há alteração para um ou mais status e você deseja incluí-los na saída, a consulta acima precisaria usar
cross join
para primeiro criar as linhas no conjunto de resultados. Não está claro se isso é um requisito, então estou deixando de fora essa complicação.