Need to group records based on matching reversal in sql

拈花ヽ惹草 提交于 2020-03-28 07:04:04

问题


I have a tricky scenario to aggregate the data.

Data in my source table is as follows.

CustomerId  Transaction Type    Transaction Amount
1               Payment              100
1               ReversePayment      -100
1               payment              100
1               ReversePayment      -100
1               Payment              100
1               Payment              100

Requirement is as follows:

  • If the payment as a assoociated Reversepayment with matched amount, sum these two records.
  • If the payment does not have an associated Reverse payment, consider it as orphan(dont sum it).

I want output to be like this.

  CustomerId    Transaction Type                Transaction Amount
   1                Payment,ReversePayment               0
   1                payment,ReversePayment               0
   1                payment                             100
   1               Payment                              100

In this scenario,

  • First record which is payment has an associated reverse payment (2nd record), Hence the sum becomes 0
  • Third record which is payment has an associated reverse payment (4th record), then the sum becomes 0
  • Fifth and sixth does not have associated reversals. dont sum these records.

Second Example:

Data in the source as follows:

 CustomerId Transaction Type    Transaction Amount
 1              Payment              100
 1              ReversePayment      -100
 1              payment              300
 1              ReversePayment      -300
 1               Payment              400
 1               Payment              500

Expected Output

CustomerId      Transaction Type                Transaction Amount
 1              Payment,ReversePayment               0
 1              payment,ReversePayment               0
 1              payment                             400
 1              Payment                             500

Second example requirement: -As first and second records (payment and its associated reverse payment got matched) ,sum these two records, output is 0. - As third and fourth records (payment and its associated reverse payment got matched), sum these two records, output is 0. - Fifth and sixth does not have associated reversals. don't sum these records.

I got solutions in group, but data is not always guaranteed to have orphan records as 'payments'. Some times they are 'Payments' and some times they are 'ReversePayments'. Can some help me get ouptut like the below (using rank or rownumber functions ) so that i can group by using RRR column.

CustomerId  Transaction Type    Transaction Amount         RRR
 1              Payment              100                   1
 1              ReversePayment      -100                   1
 1              payment              100                   2
 1              ReversePayment      -100                   2
 1               Payment              100                   3
 1               Payment              100                   4


 CustomerId Transaction Type    Transaction Amount      RRR 
 1              Payment              100                 1
 1              ReversePayment      -100                 1
 1              payment              300                 2
 1              ReversePayment      -300                 2
 1               Payment              400                3
 1               Payment              500                4   

回答1:


You can enumerate the different types and then aggregate:

select customerid,
       listagg(ttype, ',') within group (order by ttype) as types,
       sum(amount) as amount
from (select t.*,
             row_number() over (partition by customerid, ttype, amount order by customerid) as seqnum
      from t
     ) t
group by customerid, seqnum;



回答2:


Edited to include your second scenario:

Using rownum to enforce inherent ordering (i.e. transactions happened in the order you've listed ), since your example is missing a transaction id or transaction time

    SQL> select * from trans_data2;

    CUSTOMER_ID TRANSACTION_TY TRANSACTION_AMOUNT
    ----------- -------------- ------------------
              1 Payment                       100
              1 ReversePayment               -100
              1 payment                       300
              1 ReversePayment               -300
              1 Payment                       400
              1 Payment                       500

    6 rows selected.


    SQL> select customer_id,
      2      case
      3          when upper(next_transaction) = 'REVERSEPAYMENT' then transaction_type||','||next_transaction
      4          else transaction_type
      5      end transaction_type,
      6      case
      7          when upper(next_transaction) = 'REVERSEPAYMENT' then transaction_amount + next_transaction_amount
      8          else transaction_amount
      9      end transaction_amount
     10  from (
     11      select customer_id, transaction_type, transaction_amount,
     12      lead (transaction_type) over ( partition by customer_id order by transaction_id ) next_transaction,
     13      nvl(lead (transaction_amount) over ( partition by customer_id order by transaction_id),0)  next_transaction_amount
     14      from ( select rownum transaction_id, t.* from trans_data2 t )
     15  ) where upper(transaction_type) = 'PAYMENT'
     16  ;

    CUSTOMER_ID TRANSACTION_TYPE              TRANSACTION_AMOUNT
    ----------- ----------------------------- ------------------
              1 Payment,ReversePayment                         0
              1 payment,ReversePayment                         0
              1 Payment                                      400
              1 Payment                                      500


来源:https://stackoverflow.com/questions/60229315/need-to-group-records-based-on-matching-reversal-in-sql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!