Добре, това ще бъде трудно за обяснение.
На всяка дата за всеки статус трябва да преброите две стойности:
- Броят клиенти, които започват с този статус.
- Броят клиенти, които си тръгват с този статус.
Първата стойност е лесна. Това е просто агрегиране на транзакциите по дата и статус.
Втората стойност е почти толкова лесна. Получавате предишния код на състояние и пребройте колко пъти този код на състояние "напуска" на тази дата.
Тогава ключът е кумулативната сума на първата стойност минус кумулативната сума на втората стойност.
Направо признавам, че следният код не е тестван (ако имате SQL Fiddle, ще се радвам да го тествам). Но ето как изглежда получената заявка:
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;
Ако имате дати, на които няма промяна за един или повече състояния и искате да ги включите в изхода, тогава горната заявка ще трябва да използва cross join
за да създадете първо редовете в резултатния набор. Не е ясно дали това е изискване, така че пропускам това усложнение.