I have following data:
lbid | lbdate | lbtype | lbamount
-----+------------+---------------+---------
1 | 2017-11-01 | Add Plafon | 20
2 | 2017-11-02 | Use Balance | 5
3 | 2017-11-03 | Add Balance | 1
4 | 2017-11-04 | Reduce Plafon | 10
5 | 2017-11-06 | Use Balance | 8
6 | 2017-11-07 | Add Balance | 2
7 | 2017-11-08 | Reduce Plafon | 5
8 | 2017-11-10 | Add Plafon | 10
9 | 2017-11-11 | Use Balance | 1
10 | 2017-11-12 | Reduce Plafon | 5
Basically the end result I expect look like this:
lbid | lbdate | lbtype | lbamount | sumplafon | sumbalance
-----+------------+---------------+-----------+-----------+-------------
1 | 2017-11-01 | Add Plafon | 20 | 20 | 20
2 | 2017-11-02 | Use Balance | 5 | 20 | 15
3 | 2017-11-03 | Add Balance | 1 | 20 | 16
4 | 2017-11-04 | Reduce Plafon | 10 | 10 | 10
5 | 2017-11-06 | Use Balance | 8 | 10 | 2
6 | 2017-11-07 | Add Balance | 2 | 10 | 4
7 | 2017-11-08 | Reduce Plafon | 5 | 5 | 4
8 | 2017-11-10 | Add Plafon | 10 | 15 | 14
9 | 2017-11-11 | Use Balance | 1 | 15 | 15
10 | 2017-11-12 | Reduce Plafon | 5 | 10 | 10
sumplafon is sum of all lbamount which lbtype are Add Balance (positive) and Reduce Balance (negative, to substract the sumplafon).
I already did it by doing this.
sum(
case
when "lbtype" = 'Add Plafon' then "lbamount"
when "lbtype" = 'Reduce Plafon' then -1 * "lbamount"
else 0
end
) over (order by "lbdate") sumplafon
And the sumbalance is sum of all lbamount which lbtype are Add Plafon (postive), Use Balance (postive), Use Balance (negative), but every time lbtype Reduce Plafon is found, the sumbalance will be reset to sumplafon if the sumbalance is greater than sumplafon.
For example lbid 4 which lbtype is Reduce Plafon, the sumbalance is 16 and it is greater than sumplafon 10, therefor the sumbalance need to be reset to its sumplafon which is 10, and then continue again the cummulative sum of the sumbalance.
I tried it by preparing the group by first in cte with count like this.
count(
case when "lbtype" = 'Reduce Plafon' then 1 else null end
) over (order by "lbdate") countplafon
And then in the second cte I did sum by using partition by the countplafon in the first cte, like this:
sum(
case
when "lbtype" = 'Add Plafon' or "lbtype" = 'Add Balance' then "lbamount"
when "lbtype" = 'Use Balance' then -1 * "lbamount"
else 0
end
) over (partition by "countplafon" order by "lbdate") sumbalance
But the result is just resetting the sumbalance from beginning because it uses group by countplafon.
lbid | lbdate | lbtype | lbamount | countplafon |sumplafon | sumbalance
-----+------------+---------------+-----------+-----------+-------------|-----------
1 | 2017-11-01 | Add Plafon | 20 | 0 | 20 | 20
2 | 2017-11-02 | Use Balance | 5 | 0 | 20 | 15
3 | 2017-11-03 | Add Balance | 1 | 0 | 20 | 16
4 | 2017-11-04 | Reduce Plafon | 10 | 1 | 20 | 0
5 | 2017-11-06 | Use Balance | 8 | 1 | 20 | -8
6 | 2017-11-07 | Add Balance | 2 | 1 | 20 | -6
7 | 2017-11-08 | Reduce Plafon | 5 | 2 | 20 | 0
8 | 2017-11-10 | Add Plafon | 10 | 2 | 20 | 10
9 | 2017-11-11 | Use Balance | 1 | 2 | 20 | 9
10 | 2017-11-12 | Reduce Plafon | 5 | 3 | 20 | 0
Here is the sqlfiddle .
Here is the sql.
with
cte_runningnumbers1
as (
select
"lbid",
"lbdate",
"lbtype",
"lbamount",
count(
case when "lbtype" = 'Reduce Plafon' then 1 else null end
) over (order by "lbdate") countplafon,
sum(
case
when "lbtype" = 'Add Plafon' then "lbamount"
when "lbtype" = 'Reduce Plafon' then -1 * "lbamount"
else 0
end
) over (order by "lbdate") sumplafon
from "lb"
),
cte_runningnumbers2 as (
select
*,
sum(
case
when "lbtype" = 'Add Plafon' or "lbtype" = 'Add Balance' then "lbamount"
when "lbtype" = 'Use Balance' then -1 * "lbamount"
else 0
end
) over (partition by "countplafon" order by "lbdate") sumbalance
from "cte_runningnumbers1"
)
select *
from cte_runningnumbers2
I was following this SO question , but I'm still confuse how to solve my problem.
The last step I need to do is to add it with the previous sumbalance or sumplafon (if the sumbalance is greater than sumplafon), but I don't know how to do it. Can anyone help me?
Create a custom aggregate function. Place the logic in a state transition function:
create or replace function lb_agg_fun(sumbalance numeric, lbtype text, lbamount numeric)
returns numeric language sql as $$
select case
when lbtype in ('Add Plafon', 'Add Balance') then sumbalance + lbamount
when lbtype = 'Use Balance' then sumbalance - lbamount
else case
when lbamount < sumbalance then lbamount
else sumbalance
end
end;
$$;
create aggregate lb_agg(text, numeric) (
sfunc = lb_agg_fun,
stype = numeric,
initcond = 0
);
And use it:
select *, lb_agg(lbtype, lbamount) over (order by lbdate) as sumbalance
from lb;
lbid | lbdate | lbtype | lbamount | sumbalance
------+------------+---------------+----------+------------
1 | 2017-11-01 | Add Plafon | 20 | 20
2 | 2017-11-02 | Use Balance | 5 | 15
3 | 2017-11-03 | Add Balance | 1 | 16
4 | 2017-11-04 | Reduce Plafon | 10 | 10
5 | 2017-11-06 | Use Balance | 8 | 2
6 | 2017-11-07 | Add Balance | 2 | 4
7 | 2017-11-08 | Reduce Plafon | 5 | 4
8 | 2017-11-10 | Add Plafon | 10 | 14
9 | 2017-11-11 | Use Balance | 1 | 13
10 | 2017-11-12 | Reduce Plafon | 5 | 5
(10 rows)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.