我有以下数据:
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
基本上我期望的最终结果如下:
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是所有lbamount的总和,其中lbtype是Add Balance(正数)和Reduce Balance(负数,以减去sumplafon)。
我已经这样做了。
sum(
case
when "lbtype" = 'Add Plafon' then "lbamount"
when "lbtype" = 'Reduce Plafon' then -1 * "lbamount"
else 0
end
) over (order by "lbdate") sumplafon
并且总和是所有lbamount的总和,其中lbtype是Add Plafon(postive),Use Balance(postive),Use Balance(negative),但每次lbtype Reduce Plafon被找到时,sumbalance将被重置为sumplafon,如果sumbalance大于sumplafon。
例如lbid 4,其中lbtype是Reduce Plafon,总和是16并且它大于sumplafon 10,因此需要将sumbalance重置为其10的sumplafon,然后再次继续sumbalance的累积和。
我尝试通过首先在cte中准备这个小组,并计算这样的数量。
count(
case when "lbtype" = 'Reduce Plafon' then 1 else null end
) over (order by "lbdate") countplafon
然后在第二个cte中我通过第一个cte中的countplafon使用分区求和,如下所示:
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
但结果只是从开始重置平衡,因为它使用了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
这是sqlfiddle。
这是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
我正在关注此SO question,但我仍然对如何解决问题感到困惑。
我需要做的最后一步是将它添加到之前的平衡或sumplafon(如果sumbalance大于sumplafon),但我不知道该怎么做。任何人都可以帮助我吗?
答案 0 :(得分:1)
创建custom aggregate 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
);
并使用它:
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)