用于分配付款的 Oracle SQL 查询

Posted

技术标签:

【中文标题】用于分配付款的 Oracle SQL 查询【英文标题】:Oracle SQL Query for distributing payments 【发布时间】:2014-06-26 19:37:54 【问题描述】:

我正在尝试在多个发票交易中实现付款分配,作为批处理的一部分。发票和付款交易保存在同一个表中,充当交易记录。

例如。我们的交易登记表中有:

ID,   USER ,  TYPE     , AMOUNT   
1     Mr. X   Invoice      1000   
2     Mr. X   Invoice      2000   
3     Mr. X   Invoice      1000   
4     Mr. X   Payment     -3000   
5     Mr. X   Payment      -500   

我正在寻找一个查询,该查询将为此用户支付 3500 的总付款,从第一张发票开始,将付款分配到每张发票并将其转储到新表中。

新表的最终结果如下。

ID    User ,  TYPE     ,   AMOUNT   , AMOUNT_PAID
1     Mr. X   Invoice        1000            1000
2     Mr. X   Invoice        2000            2000
3     Mr. X   Invoice        1000            500

我试图避免在 PL/SQL 块中使用循环。 任何 cmets 都非常感谢!

【问题讨论】:

对于给定用户(或您的实际分组密钥是什么)是否可以进行多次付款? 是的,一个用户可以支付超过 1 次付款。因此,我们正在尝试将付款总和分配给各个发票。如果付款超过,最后一张发票将被多付的金额多付。我对帖子进行了一些编辑以表示多次付款。 【参考方案1】:

所以这个解决方案使用了两个分析函数。在内部查询中,它使用分析 SUM() 来跟踪发票金额的滚动总计。在外部查询中,当支付的总金额不足时,它使用 LAG() 来获取先前的发票总和。

select id
       , username
       , amount
       , case when tot_amount >= rolling_pay
              then amount
         else
              tot_amount - lag(rolling_pay) over (order by id)
         end as amount_paid
from (
   with inv as (select id
                         , username
                         , amount 
                 from transactions
                 where type = 'Invoice' )
         , pay as ( select username
                            , abs(sum(amount)) as tot_amount 
                 from transactions
                 where type = 'Payment'
                 group by username )
    select inv.id
           , inv.username
           , inv.amount
           , pay.tot_amount
           , sum(inv.amount) over (partition by inv.username order by inv.id) as rolling_pay
    from inv join pay 
         on inv.username = pay.username
    order by inv.username, inv.id
  )

注意:当每个业务密钥超过一个时,我将付款相加。

这是 inevitable SQL Fiddle 证明这会产生所需的结果。

【讨论】:

哇!那工作完美无缺。我需要花一些时间来研究分析函数,以便我可以调整它来处理多付的情况。非常感谢! 这对我在 Postgresql 中同样适用...谢谢。

以上是关于用于分配付款的 Oracle SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章