我的下表包含以下列
payments
recipient_id, sender_id, amount
我想总结每个ID
的金额如下所示
select -sum(amount) from payments group by sender_id
select sum(amount) from payments group by recipient_id
它为我提供了从每个发件人帐户中删除的金额以及从每个收件人帐户中添加的金额。
如何将这两个查询合并为一个查询,以便我可以获取收件人和发件人ID的金额?请注意,sender_id和recipient_id可能会重叠。就像收件人可以是另一个查询中的发件人另一个交易。请注意,如果发件人的金额为负数,如果是收件人,则金额必须为正数。 (发件人赔钱,收款人拿钱)
所以基本上如果我有以下数据
recipient_id sender_id amount
1 2 50
2 3 100
2 4 150
3 1 50
我应该得到以下结果
account_id, amount
1 0
2 200 (sent 50, got 250)
3 -50 ( sent 100, got 50)
4 -150 (sent 150 dollars)
答案 0 :(得分:1)
select (case when recipient_id < sender_id then recipient_id else sender_id end) as id1,
(case when recipient_id < sender_id then sender_id else recipient_id end) as id2,
sum(case when recipient_id < sender_id then amount else - amount end) as netamount
from payments
group by (case when recipient_id < sender_id then recipient_id else sender_id end),
(case when recipient_id < sender_id then sender_id else recipient_id end);
它通常报告成对的id,较小的是第一个。它会增加较小的ID是收件人的金额,并减去较小的ID是发件人的金额。
这假设任何给定的交易在数据中出现一次。
答案 1 :(得分:1)
以下是使用CTE编写此查询的一种方法。使用收件人的正数和发件人的负数,从表中选择两次金额:
;with Transactions (ID, amount) as
(
select sender_id, -amount
from Payments
union all
select recipient_id, amount
from Payments
)
select ID as Account_ID, sum(amount) as Amount
from Transactions
group by ID
使用以下代码进行测试:
if object_id('Payments') is null
begin
create table Payments
(
recipient_id int,
sender_id int,
amount int
)
insert into Payments (recipient_id, sender_id, amount)
select 1, 2, 50
union select 2, 3, 100
union select 2, 4, 150
union select 3, 1, 50
end
结果:
Account_ID Amount
1 0
2 200
3 -50
4 -150
这种方法的问题在于它会两次扫描Payments表。以下是使用CROSS APPLY
的另一种方法,该方法遍历表格一次:
select ID as Account_ID, sum(Transactions.amount) as Amount
from Payments p
cross apply
(
values
(p.recipient_id, p.amount),
(p.sender_id, -p.amount)
) as Transactions (ID, amount)
group by ID
结果:
Account_ID Amount
1 0
2 200
3 -50
4 -150