Reputation: 4595
I have a query that looks more or less like this:
INSERT INTO #results
SELECT Name,
(SELECT
SUM(CAST(Amount AS BIGINT))
FROM Items
WHERE RemittingMember = a.Number
and RecordId = 50),
(SELECT SUM(CAST(Std_Amount AS BIGINT))
FROM Items
WHERE RemittingMember = a.Number
AND RecordId = 10)
FROM Member a
where Amount
is a currency (stored as a varchar, without a decimal), RemittingMember
is a link between the Items
table and the Member
table and RecordId
indicates what type of item the row is. In this case, a 50 is a debit and a 10 is a credit.
I need to subtract the first column from the second column and have that value in a third column. I know I can do this as follows:
INSERT INTO #results
SELECT Name,
(SELECT
SUM(CAST(Amount AS BIGINT))
FROM Items
WHERE RemittingMember = a.Number
and RecordId = 50),
(SELECT SUM(CAST(Std_Amount AS BIGINT))
FROM Items
WHERE RemittingMember = a.Number
AND RecordId = 10),
(SELECT
SUM(CAST(Amount AS BIGINT))
FROM Items
WHERE RemittingMember = a.Number
and RecordId = 50) - (SELECT SUM(CAST(Std_Amount AS BIGINT))
FROM Items
WHERE RemittingMember = a.Number
AND RecordId = 10)
FROM Member a
But this is rather difficult to read and cumbersome to change if changes ever need to be made. I also know I can do this with local variables, but this is a report where a.Number
will change which will involve iteration which I want to avoid.
I also need to check the sign of this third column to put a value in a fourth column.
Is there a clever way of achieving this?
Upvotes: 2
Views: 2000
Reputation: 920
You should be able to simplify the query even more to remove an additional join onto the items table. Something like this should work. Needs to be tested with your data
SELECT
name,
debit,
credit,
Amount = debit - credit,
[SIGN] = SIGN(debit - credit)
FROM Member a
inner join(
SELECT
RemittingMember,
debit=SUM(CASE WHEN RecordId = 50 THEN CAST(Amount AS BIGINT) ELSE 0 END),
credit=SUM(CASE WHEN RecordId = 10 THEN CAST(Std_Amount AS BIGINT) ELSE 0 END)
FROM Items
WHERE RecordId IN(10,50)
GROUP BY
RemittingMember
) as Amts
on Amts.RemittingMember = a.Number
Upvotes: 0
Reputation: 2427
You can use CTE, something like this:
;WITH intermediate_results (name, debit, credit)
AS (
SELECT
Name
AS name,
(SELECT
SUM(CAST(Amount AS BIGINT))
FROM Items
WHERE RemittingMember = a.Number
and RecordId = 50)
AS debit,
(SELECT SUM(CAST(Std_Amount AS BIGINT))
FROM Items
WHERE RemittingMember = a.Number
AND RecordId = 10)
AS credit
FROM Member a
)
INSERT INTO #results
SELECT name, debit, credit, debit - credit, SIGN(debit - credit)
FROM intermediate_results
Upvotes: 2
Reputation: 5120
You can use outer apply
statement:
INSERT INTO #results
SELECT Name,
s1.Value,
s2.Value,
s2.Value - s1.Value,
case
when s2.Value > s1.Value then 1
when s2.Value < s1.Value then -1
else 0
end
FROM Member a
outer apply (SELECT
SUM(CAST(Amount AS BIGINT)) Value
FROM Items
WHERE RemittingMember = a.Number
and RecordId = 50) s1
outer apply (SELECT
SUM(CAST(Std_Amount AS BIGINT)) Value
FROM Items
WHERE RemittingMember = a.Number
and RecordId = 10) s2
Upvotes: 1