sql - 需要根据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。 - 第五和第六没有关联的冲销。不要总结这些记录。
我在小组中得到了解决方案,但数据并不总是保证有孤立记录作为“付款”。有时它们是“付款”,有时它们是“反向付款”。可以帮助我获得如下所示的输出(使用排名或行号函数),以便我可以使用 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
解决方案
编辑以包括您的第二种情况:
使用 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
推荐阅读
- html - 样式表未正确使用 html 文件,但它适用于其他 html 文件
- azure - Azure 服务总线主题重复检测
- c# - C#:如果我只有它的名称,如何使用按钮(fe,甚至其他对象)?
- azure-active-directory - Webview2 SPA SSO
- corda - Corda 节点连接到 Oracle 数据库时无法启动
- java - 如何在片段重新创建中从firebase恢复已在recyclerview中获取的数据
- pytorch - 如何通过访问 pytorch 中 2 X 2 张量的给定索引处的特定值来创建张量?
- c++ - C++ 通用回调实现
- javascript - 如何触发同时点击画布对象和放置在对象顶部的DOM元素?
- c++ - 将每一行解析为数组中的变量