1

バッチ プロセスの一部として、複数の請求書トランザクションで支払いを分配しようとしています。請求書と支払いトランザクションは、トランザクション レジスタとして機能する同じテーブルに保持されます。

だから例えば。トランザクション登録テーブルには次のものがあります。

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 ブロックでループを使用しないようにしています。どんなコメントでも大歓迎です!

4

1 に答える 1

4

したがって、このソリューションでは 2 つの分析関数を使用します。内部クエリでは、分析 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
  )

注: ビジネス キーごとに複数ある場合に備えて、支払いを合計しました。

これは、これが望ましい結果を生み出すことを示す必然的な SQL Fiddleです。

于 2014-06-26T20:13:33.257 に答える