Reputation: 946
I am trying to group the credit and debit account numbers for money transaction.
http://sqlfiddle.com/#!18/67ecd/4/0
I am able to group if there are multiple transactions on the same credit and debit account.
CREATE Table TestTable
(
DebitAccountNumber NVARCHAR(10),
CredtiAccountNumber NVARCHAR(10),
Amount MONEY
)
INSERT INTO TestTable
VALUES ('A', 'C', 10), ('C', 'A', 20), ('A', 'C', 40);
SELECT
DebitAccountNumber,
CredtiAccountNumber,
SUM(amount)
FROM
TestTable
GROUP BY
DebitAccountNumber, CredtiAccountNumber
Since credit and debit account is happening on the same account, the expected output is A -> C 30.
Could anyone please help me with the query?
Upvotes: 2
Views: 70
Reputation: 870
Based on @GordonLinoff's approach, having in mind the result, you accepted from @dnoeth, my suggested answer would be:
SELECT v.CreditAccountNumber, v.DebitAccountNumber, SUM(v.Amount) AS SumAmount
FROM TestTable AS tt
CROSS APPLY
(VALUES
(DebitAccountNumber, CreditAccountNumber, Amount),
(CreditAccountNumber, DebitAccountNumber, -Amount)
) AS v(DebitAccountNumber, CreditAccountNumber, Amount)
GROUP BY v.CreditAccountNumber, v.DebitAccountNumber
HAVING SUM(v.Amount) > 0
ORDER BY 1, 2;
Here's a fiddle for it.
Upvotes: 0
Reputation: 60462
WITH cte AS
(
SELECT
-- "normalize" debitor and creditor to: account#1 < account#2
CASE WHEN DebitAccountNumber < CreditAccountNumber THEN DebitAccountNumber ELSE CreditAccountNumber END AS Account1,
CASE WHEN DebitAccountNumber < CreditAccountNumber THEN CreditAccountNumber ELSE DebitAccountNumber END AS Account2,
-- adjust sign when accounts switched
CASE WHEN DebitAccountNumber < CreditAccountNumber THEN Amount ELSE -Amount END AS amount
FROM TestTable
)
SELECT
Account1,
Account2,
Sum(amount) -- might be negative
FROM cte
GROUP BY
Account1,
Account2
;
See fiddle
Edit:
If you want to avoid negative amounts you can "normalize" it again:
WITH normalized AS
(
SELECT
-- "normalize" debitor and creditor to: account#1 < account#2
CASE WHEN DebitAccountNumber < CreditAccountNumber THEN DebitAccountNumber ELSE CreditAccountNumber END AS Account1,
CASE WHEN DebitAccountNumber < CreditAccountNumber THEN CreditAccountNumber ELSE DebitAccountNumber END AS Account2,
-- adjust sign when accounts switched
CASE WHEN DebitAccountNumber < CreditAccountNumber THEN Amount ELSE -Amount END AS amount
FROM TestTable
),
summed as
(
SELECT
Account1,
Account2,
Sum(amount) as Amount -- might be negative
FROM normalized
GROUP BY
Account1,
Account2
)
select
case when Amount > 0 then Account1 else Account2 end as Debitor,
case when Amount > 0 then Account2 else Account1 end as Creditor,
abs(Amount) as Amount
from summed
;
See fiddle
Upvotes: 1
Reputation: 1269803
I suspect you want:
select accountnumber, sum(amount)
from ((select DebitAccountNumber as accountnumber, - amount as amount
from testtable
) union all
(select CreditAccountNumber as accountnumber, amount
from testtable
)
) cd
group by accountnumber;
In SQL Server, you can use apply
:
select v.accountnumber, sum(v.amount)
from testtable tt cross apply
(values (debitaccountnumber, - amount), (creditaccountnumber, amount)
) v(accountnumber, amount)
group by v.accountnumber;
Upvotes: 3