如何防止 SQL 中的负收入值并将其重新分配到接下来的月份?

问题描述 投票:0回答:1

我在 SQL 中有一个收入表,其中包含日期和收入列。我想创建一个防止负收入值的逻辑,以便将任何负收入值设置为 0,并从接下来几个月的收入中减去负数,直到完全抵消。

比如我有以下收入数据:

日期 收入
2018-09-01 1200
2018-08-01 400
2018-07-01 -1000
2018-06-01 800
2018-05-01 600
2018-04-01 200
2018-03-01 -200
2018-02-01 400
2018-01-01 200

预期输出应该是:

日期 收入
2018-09-01 600
2018-08-01 0
2018-07-01 0
2018-06-01 800
2018-05-01 600
2018-04-01 0
2018-03-01 0
2018-02-01 400
2018-01-01 200

这里是一些入门代码


WITH revenue_table AS (
    SELECT '2018-09-01' AS date, 1200 AS revenue UNION ALL
    SELECT '2018-08-01' AS date, 400 AS revenue UNION ALL
    SELECT '2018-07-01' AS date, -1000 AS revenue UNION ALL
    SELECT '2018-06-01' AS date, 800 AS revenue UNION ALL
    SELECT '2018-05-01' AS date, 600 AS revenue UNION ALL
    SELECT '2018-04-01' AS date, 200 AS revenue UNION ALL
    SELECT '2018-03-01' AS date, -200 AS revenue UNION ALL
    SELECT '2018-02-01' AS date, 400 AS revenue UNION ALL
    SELECT '2018-01-01' AS date, 200 AS revenue
)

select * from revenue_table

我不确定如何解决这个问题。任何人都可以提出解决方案或提供一些实现此逻辑的示例代码吗?

  • 试图在负值上创建滚动总和并减去正值
  • 递归,但看起来很慢而且没有真正起作用
sql postgresql recursive-query
1个回答
0
投票

如果我正确地回答了这个问题,我们确实需要在这里递归,以便我们可以迭代地将负数分配到以下行。

least
greatest
应该足够好算术:

with recursive
    data as (
        select r.*, row_number() over(order by date) rn from revenue_table r
    ),
    rcte (date, old_revenue, rn, new_revenue, rest) as (
        select null::date, 0, 0::bigint, 0, 0
        union all
        select d.*, greatest(d.revenue + r.rest, 0), least(d.revenue + r.rest, 0)
        from rcte r
        inner join data d on d.rn = r.rn + 1
    )
select date, old_revenue, new_revenue 
from rcte 
where rn > 0 order by date desc
约会 old_revenue 新收入
2018-09-01 1200 600
2018-08-01 400 0
2018-07-01 -1000 0
2018-06-01 800 800
2018-05-01 600 600
2018-04-01 200 0
2018-03-01 -200 0
2018-02-01 400 400
2018-01-01 200 200

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.