簡體   English   中英

需要根據sql中的匹配反轉對記錄進行分組

[英]Need to group records based on matching reversal in sql

我有一個棘手的場景來聚合數據。

我的源表中的數據如下。

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

要求如下:

  • 如果付款為具有匹配金額的關聯反向付款,則將這兩個記錄相加。
  • 如果付款沒有關聯的反向付款,則將其視為孤兒付款(不要匯總)。

我希望輸出是這樣的。

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

在這種情況下,

  • 第一條付款記錄具有關聯的反向付款(第二條記錄),因此總和變為 0
  • 付款的第三條記錄具有關聯的反向付款(第四條記錄),則總和變為 0
  • 第五和第六沒有相關的逆轉。 不要總結這些記錄。

第二個例子:

源中數據如下:

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

預期產出

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

第二個示例要求: - 作為第一條和第二條記錄(付款及其關聯的反向付款匹配),將這兩條記錄相加,輸出為 0。 - 作為第三條和第四條記錄(付款及其相關的反向付款匹配),將這兩項相加記錄,輸出為 0。 - 第五和第六沒有關聯的逆轉。 不要總結這些記錄。

我在小組中得到了解決方案,但數據並不總是保證將孤立記錄作為“付款”。 有時它們是“付款”,有時它們是“反向付款”。 可以幫助我獲得如下輸出(使用 rank 或 rownumber 函數),以便我可以使用 RRR 列進行分組。

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   

您可以枚舉不同的類型,然后聚合:

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;

編輯以包括您的第二個場景:

使用 rownum 強制執行固有排序(即交易按照您列出的順序發生),因為您的示例缺少交易 ID 或交易時間

    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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM