How to SUM columns on multiple conditions in a GROUP BY
I am trying to return a list of Accounts with their Balances, Outcome and Income
Account Transaction
------- -----------
AccountID TransactionID
BankName AccountID
Locale Amount
Status
Here is what I currently have. Could someone explain where I am going wrong?
select
a.ACCOUNT_ID,
a.BANK_NAME,
a.LOCALE,
a.STATUS,
sum(t1.AMOUNT) as BALANCE,
sum(t2.AMOUNT) as OUTCOME,
sum(t3.AMOUNT) as INCOME
from ACCOUNT a
left join TRANSACTION t1 on t1.ACCOUNT_ID = a.ACCOUNT_ID
left join TRANSACTION t2 on t2.ACCOUNT_ID = a.ACCOUNT_ID and t2.AMOUNT < 0
left join TRANSACTION t3 on t3.ACCOUNT_ID = a.ACCOUNT_ID and t3.AMOUNT > 0
group by a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]
UPDATE
Have corrected the t2 left join syntax as per the comment below.
The output I am expecting is hopefully obvious from the question. For 6 accounts, the SQL should return 6 accounts with their Balance, Income and Outcome of that account.
The problem with the SQL I prov开发者_StackOverflow社区ided was that the numbers are wrong! As per the comments I think the problem stems from joining multiple times which is summing the amounts incorrectly.
Since you didn't tell us what's going wrong (that is, describe the behavior you get in addition to describing the the behavior you expect), it's hard to say where, but there are a couple of possibilities. Neil points out one. Another is that since you join on the transaction table three times, you're pairing transactions with transactions and getting repetitions. Instead, join on the transaction table a single time and change how you sum up the Amount
column.
Select
a.ACCOUNT_ID,
a.BANK_NAME,
a.LOCALE,
a.STATUS,
sum(t.AMOUNT) as BALANCE,
sum((t.AMOUNT < 0) * t.AMOUNT) As OUTGOING,
sum((t.AMOUNT > 0) * t.AMOUNT) As INCOMING
From ACCOUNT a
Left Join TRANSACTION t On t.ACCOUNT_ID = a.ACCOUNT_ID
Group By a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]
You can use CASE
expressions as a more readable alternative to the multiplications:
Select
a.ACCOUNT_ID,
a.BANK_NAME,
a.LOCALE,
a.[STATUS],
sum(t.AMOUNT) As BALANCE,
sum(CASE WHEN t.AMOUNT < 0 THEN t.AMOUNT ELSE 0 end) As OUTCOME,
sum(CASE WHEN t.AMOUNT > 0 THEN t.AMOUNT ELSE 0 end) As INCOME
From ACCOUNT a
Left Join [TRANSACTION] t On t.ACCOUNT_ID = a.ACCOUNT_ID
Group By a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]
Did you mean:
select
a.ACCOUNT_ID,
a.BANK_NAME,
a.LOCALE,
a.STATUS,
sum(t1.AMOUNT) as BALANCE,
sum(CASE WHEN t2.AMOUNT < 0 THEN t2.Amount ELSE 0 END) as OUTCOME,
sum(CASE WHEN t3.AMOUNT > 0 THEN t3.Amount ELSE 0 END) as INCOME
from
ACCOUNT a
left join TRANSACTION t1 on t1.ACCOUNT_ID = a.ACCOUNT_ID
left join TRANSACTION t2 on t2.ACCOUNT_ID = a.ACCOUNT_ID
left join TRANSACTION t3 on t3.ACCOUNT_ID = a.ACCOUNT_ID
group by
a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]
I'm not sure why you would need the multiple joins. Couldn't you simply do something like:
Select
a.ACCOUNT_ID
, a.BANK_NAME
, a.LOCALE
, a.STATUS
, Sum ( t.Amount ) As Balance
, Sum( Case When t.Amount < 0 Then Amount End ) As Outcome
, Sum( Case When t.Amount > 0 Then Amount End ) As Income
From ACCOUNT a
Left Join TRANSACTION t
On t.ACCOUNT_ID = a.ACCOUNT_ID
Group By a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]
The join for TRANSACTION t2 should be on t2 as in on t2.ACCOUNT_ID = a.ACCOUNT_ID
精彩评论