D'accord, ça va être difficile à expliquer.
A chaque date pour chaque statut, vous devez compter deux valeurs :
- Le nombre de clients qui commencent avec ce statut.
- Le nombre de clients qui partent avec ce statut.
La première valeur est facile. Il s'agit simplement de l'agrégation des transactions par date et statut.
La deuxième valeur est presque aussi simple. Vous obtenez le précédent code de statut et comptez le nombre de fois que ce code de statut "part" à cette date.
Ensuite, la clé est la somme cumulée de la première valeur moins la somme cumulée de la seconde valeur.
J'admets librement que le code suivant n'est pas testé (si vous aviez un SQL Fiddle, je serais heureux de le tester). Mais voici à quoi ressemble la requête résultante :
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;
Si vous avez des dates où il n'y a pas de changement pour un ou plusieurs statuts et vous voulez les inclure dans la sortie, alors la requête ci-dessus devra utiliser cross join
pour créer d'abord les lignes dans le jeu de résultats. Il n'est pas clair s'il s'agit d'une exigence, donc je laisse de côté cette complication.