2014-09-19 58 views
1

我有以下幾列於下表我怎麼能寫一個雙重分組依據查詢

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

如果你想顯示他們並排,你需要知道他們是如何彼此關聯。你是否希望它按照X發件人發送給Y收件人的所有時間進行分組? – paqogomez 2014-09-19 21:31:52

+0

什麼是數據庫系統? MySQL的? SQL Server?甲骨文? – 2014-09-20 17:12:55

回答

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); 

它一般報告成對的ids,其中較小的是第一個。它在較小的id是收件人的地方添加金額,並在較小的id是發件人的地方減去金額。

這假設任何給定的事務都會在數據中出現一次。

+0

我經常使用這種結構,所以它絕對應該工作(除非我看不到語法錯誤)。 – 2014-09-19 21:57:55

1

以下是使用CTE編寫此查詢的一種方法。

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 

結果::用下面的代碼測試

;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 

:使用收件人的正量和發送者的負量從表中選擇的兩倍的量

Account_ID Amount 
1   0 
2   200 
3   -50 
4   -150 

的這種方法的問題在於它掃描付款表兩次。下面是使用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 
+0

我不認爲我的MySQL客戶端支持交叉應用.. – Jasmine 2014-09-20 00:33:52