How to subtract 2 SUM in SQL query - sql

I want to find the total outstanding amount for a particular item amount excluding the refund amount.
There will be two columns for each item based on number of times it was sold, final_amount and 2nd refund_amount for each items and I want to subtract total refund_amount from final_amount for each item.
PFB the code/query
SELECT item_id,
SUM(final_amount) as total_amount,
SUM(ISNULL(refund_amount, 0)) AS total_refund
SUM(final_amount) - SUM(ISNULL(refund_amount, 0)) AS outstanding_amount
FROM tabel1
WHERE item_id in ('119688521',
'109536343',
'99459466',
'97126817',
'138148320',
'107816131')
GROUP BY 1
I am getting a syntax error for "SUM" near
SUM(final_amount)-SUM(ISNULL(refund_amount, 0)) AS outstanding_amount
I tried different code:
SUM(total_amount - total_refund) AS npv
And I got the same error.

First off, there's a few errors in syntax. You're missing a comma between all the select-elements (between your total_refund and outstanding_amount). You should also check if the SUM() was null, not if the column was null. You can also use COALESCE() if you prefer that. Finally, you need to GROUP BY something useful, like the item_id.
SELECT item_id,
SUM(final_amount) as total_amount,
ISNULL(SUM(refund_amount), 0) AS total_refund,
SUM(final_amount) - ISNULL(SUM(refund_amount), 0) AS outstanding_amount
FROM tabel1 WHERE item_id in ('119688521',
'109536343',
'99459466',
'97126817',
'138148320',
'107816131')
GROUP BY item_id
Live demo at http://www.sqlfiddle.com/#!18/94f518/5

You are missing a comma. In addition, you should check for NULL after the SUM():
SELECT item_id,
SUM(final_amount) as total_amount,
COALESCE(SUM(refund_amount), 0) AS total_refund,
(SUM(final_amount) - COALESCE(SUM(refund_amount), 0)
) AS outstanding_amount
FROM tabel1
WHERE item_id in ('119688521', '109536343', '99459466', '97126817', '138148320', '107816131')
GROUP BY 1

Try this
SELECT item_id,
SUM(final_amount) as total_amount,
SUM(ISNULL(refund_amount, 0)) AS total_refund
SUM(final_amount - isnull(refund_amount, 0)) AS outstanding_amount
FROM tabel1 WHERE item_id in ('119688521',
'109536343',
'99459466',
'97126817',
'138148320',
'107816131')
GROUP BY item_id

Your are missing to put a comma (,) after your column ".... AS total_refund". Add the comma and this will resolve the syntax issue.
And please use GROUP BY item_id instead of GROUP BY 1

Related

Access SQL Calculation in SELECT make not null

I have a query that filters results for products which have had orders sent after an user-input date, and calculates what the quantity becomes if the order was sent after that date.
SELECT id, ProductName,
[OnHand]+ SUM([OrderJoin.Quantity]) AS Qty After
FROM Query3
WHERE Query3.ShippedDate > [Enter End Date] And
Query3.ShippedDate) Is Not Null
GROUP BY id, ProductName, OnHand;
But if I were to remove the WHERE statement, how would I make it so the Qty After would show as OnHand for the results that become NULL?
You would use NZ() to convert the NULL value to 0. Something like this:
SELECT id, ProductName,
NZ(OnHand, 0) + NZ(SUM([OrderJoin.Quantity]), 0) AS QtyAfter
...

Make a select with one of the column based on other select

I'm working with windev using the database hyperfile client/serveur.
I have a table named Operation with colums (accountNumber, date, amount, operationType ).
operationType can take two values: "payment" and "withdrawal".
I want to select the List of operations done in an account and, my List should display 5 colums:
Date, accountNumber, amount, operationType and balance.
The last column (balance) should be the difference between the sum of all operations done before the current date with type "payment" and the sum of all operation done before the current date with type "withdrawal"
I try the following sql code
SELECT accountNumber, date as dateOpe, amount, operationType, (SUM (SELECT Operation.amount
FROM Operation
WHERE Operation.date<=dateOpe AND Operation.operationType='payment')
-SUM (SELECT Operation.amount
FROM Operation
WHERE Operation.date<=dateOpe AND Operation.operationType='withdrawal')) as balance
FROM Operation
But I always have an error telling me that i do not have the right to put a select in the SUM
Please can somebody help me. pease how can i write a such sql query.
thanks in advance
Please try this:
SELECT accountNumber, date, amount, operationType,
(SELECT SUM(amount) AS balance
FROM operation WHERE operationType='payment' and date=date)
-(SELECT SUM(amount) AS balance
FROM operation WHERE operationType='withdrawal' and date=date)
as balance
FROM operation
Try something like the following, using a subquery to find the SUMs. There may be a more elegant solution, but this should work.
SELECT date, accountNumber,
operationType, deposits - withdrawals AS balance
FROM Operations o INNER JOIN (
SELECT accountNumber, SUM(amount) AS withdrawals
FROM Operaions
WHERE operationType = 'withdrawal'
GROUP BY accountNumber
) a ON o.accountNumber = a.accountNumber
INNER JOIN (
SELECT accountNumber, SUM(amount) AS deposits
FROM Operations
WHERE operationType = 'deposit'
GROUP BY accountNumber
)b ON o.accountNumber = b.accountNumber
I would use the fact that a logical expression yields 0 if false and 1 if true. Therefore, Operation.amount * <logical expression> will yield 0 if the expression is false and Operation.amount if the expression is true. As a result, the following query should be close to a solution (untested):
SELECT accountNumber, date as dateOpe, amount, operationType,
SUM (Operation.amount * (Operation.date<=dateOpe AND Operation.operationType='payment')) -
SUM (Operation.amount * (Operation.date<=dateOpe AND Operation.operationType='withdrawal')) as balance
FROM Operation

Adding Case in two sub queries returning null on subtract

I have two tables, both have qty column, I want to subtract issued_donated_items from donated_items. It works fine until there is not a record in issued_donated_items then my query returns null
SELECT
(
(SELECT Sum(quantity) AS tQty FROM donated_items WHERE item_id=4)
-
(SELECT Sum(quantity_issued) AS issueQty FROM issued_donated_items WHERE item_id=4)
)AS total
I would suggest moving the subqueries to the from clause and using coalesce():
SELECT (COALESCE(di.QTY, 0) - COALESCE(idi.issueQTY, 0)
) AS total
FROM (SELECT Sum(quantity) AS tQty FROM donated_items WHERE item_id = 4) di CROSS JOIN
(SELECT Sum(quantity_issued) AS issueQty FROM issued_donated_items WHERE item_id = 4) idi;
This makes it easy to re-use the values if you, for instance, want to see the two numbers as well as their difference.
Use isnull() like this:
SELECT
(
(SELECT Sum(isnull(quantity,0)) AS tQty FROM donated_items WHERE item_id=4)
-
(SELECT Sum(isnull(quantity_issued,0)) AS issueQty FROM issued_donated_items WHERE item_id=4)
)AS total
For ANSI standard SQL use coalesce() instead of isnull().

select least row per group in SQL

I am trying to select the min price of each condition category. I did some search and wrote the code below. However, it shows null for the selected fields. Any solution?
SELECT Sales.Sale_ID, Sales.Sale_Price, Sales.Condition
FROM Items
LEFT JOIN Sales ON ( Items.Item_ID = Sales.Item_ID
AND Sales.Expires_DateTime > NOW( )
AND Sales.Sale_Price = (
SELECT MIN( s2.Sale_Price )
FROM Sales s2
WHERE Sales.`Condition` = s2.`Condition` ) )
WHERE Items.ISBN =9780077225957
A little more complicated solution, but one that includes your Sale_ID is below.
SELECT TOP 1 Sale_Price, Sale_ID, Condition
FROM Sales
WHERE Sale_Price IN (SELECT MIN(Sale_Price)
FROM Sales
WHERE
Expires_DateTime > NOW()
AND
Item_ID IN
(SELECT Item_ID FROM Items WHERE ISBN = 9780077225957)
GROUP BY Condition )
The 'TOP 1' is there in case more than 1 sale had the same minimum price and you only wanted one returned.
(internal query taken directly from #Michael Ames answer)
If you don't need Sales.Sale_ID, this solution is simpler:
SELECT MIN(Sale_Price), Condition
FROM Sales
WHERE Expires_DateTime > NOW()
AND Item_ID IN
(SELECT Item_ID FROM Items WHERE ISBN = 9780077225957)
GROUP BY Condition
Good luck!

Error in query using WHERE IN

This is the query I try to run:
Select Status from [transaction] where TransactionID IN (select MAX(CAST(TransactionID AS VARCHAR(36))), sum(debit)
FROM [transaction]
WHERE dbo.getday(StartSaleTime) >= '5/1/2011' and dbo.getday(StartSaleTime) <= '5/3/2011' and Status > -1 And TransactionNo like 'EL%' And TransactionType = 4
GROUP BY CustomerID, debit HAVING ( COUNT(CustomerID) > 1 ))
it returns this error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
It tells you exactly what is wrong in the error message. When using in you can only specify one column in the select list.
If you change your query to this, it should work fine.
Select Status from [transaction] where TransactionID
IN (select MAX(CAST(TransactionID AS VARCHAR(36))) as [TransactionID]
FROM [transaction]
WHERE dbo.getday(StartSaleTime) >= '5/1/2011' and dbo.getday(StartSaleTime) <= '5/3/2011' and Status > -1 And TransactionNo like 'EL%' And TransactionType = 4
GROUP BY CustomerID, debit HAVING ( COUNT(CustomerID) > 1 ))
You can specify multiple columns but only when using EXISTS not IN
You are selecting two things and trying to use that with IN(). You should select only the ID when trying to do where someId In(list of Ids).
Your subquery has to return only a single field. Right now you're returning two, so the overall query looks kinda like:
SELECT ... WHERE TransactionID IN ((a,b), (c,d), etc...)
SQL server doesn't known which column to use for the IN stuff, so it's complaining.