如何通过查询编写双组

时间:2014-09-19 21:25:59

标签: sql

我的下表包含以下列

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)

2 个答案:

答案 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