Issues with MIN & MAX when using Case statement - sql

I am trying to generate a summary report using various aggregate functions: MIN, MAX, SUM, etc. The issue I have is when I try to get a MIN and MAX of a field when I am also using the case statement. I am unable to get the MIN value of a field when I am using the case statement. I can best explain it with sample data and the sql statement:
Fields: AccountNumber, Symbol, TradeDate, TransactionType, Price, Quantity, Amount
Table: Trades
AccountNumber, Symbol, TradeDate, TransactionType, Price, Quantity, Amount
123,"XYZ",1/2/2011,"Buy",15,100,1500
123,"XYZ",1/2/2011,"Buy",10,50,500
123,"XYZ",1/2/2011,"Sell",20,100,2000
456,"ABC",1/3/2011,"Buy",10,20,200
456,"ABC",1/3/2011,"Buy",15,30,450
789,"DEF",1/4/2011,"Sell",30,100,3000
Query:
SELECT AccountNumber,
Symbol,
SUM(case when TransactionType = "Buy" then 1 else 0) as TotalBuys,
SUM(case when TransactionType = "Sell" then 1 else 0) as TotalSells,
MIN(case when TransactionType = "Buy" then Price else 0) as MinBuy,
MAX(case when TransactionType = "Buy" then Price else 0) as MaxBuy,
MIN(case when TransactionType = "Sell" then Price else 0) as MinSell,
MAX(case when TransactionType = "Sell" then Price else 0) as MaxSell,
MIN(Price) as MinPrice,
MAX(Price) as MaxPrice
FROM Trades
Group By AccountNumber, Symbol
What I am expecting is the following results:
AccountNumber, Symbol, TotalBuys, TotalSells, MinBuy, MaxBuy, MinSell, MaxSell, MinPrice, MaxPrice
123,"XYZ",2,1,10,15,20,20,10,20
456,"ABC",2,0,10,15,0,0,10,15
789,"DEF",0,1,0,0,30,30,30,30
However, I am getting the following results:
AccountNumber, Symbol, TotalBuys, TotalSells, MinBuy, MaxBuy, MinSell, MaxSell, MinPrice, MaxPrice
123,"XYZ",2,1,**0**,15,**0**,20,**0**,20
456,"ABC",2,0,10,15,0,0,10,15
789,"DEF",0,1,0,0,30,30,30,30
When there are two different TransactionTypes for each grouping, the Min fields (MinBuy,MinSell, and MinPrice) are coming out as 0 as opposed to what is expected. What am I doing wrong on the sql statement? Is there another way to get the desired results?

Min between 0 and a positive number is 0, you should change:
MIN(case when TransactionType = "Buy" then Price else 0)
by
MIN(case when TransactionType = "Buy" then Price else Null)
Null don't compute in an aggregation function.
Thats all.
Edited 6 years later:
As P5Coder says, it is enough without else clause, also I guess the end is mandatory on some database brands. Here it is:
MIN(case when TransactionType = "Buy" then Price end)

Related

SQL - separate results of same column into different cloumns using multiple where statements

I have no prior SQL knowledge. I am trying to get sum of all debitTransactions for different transactionType for each FolioNumber
I have the following code but it gives sum of all the debit transactions for each transaction type for each folio.
But all I want is sum of all gst(106) for each folio in one column, sum of all levy(105) for each folio in second column and sum of all roomRevenue(100) for each folio in third column.
---non working code
SELECT FolioNumber,
(Select SUM(debitTransactions) FROM HISTTRN WHERE transactionType = 106) as gst,
(Select SUM(debitTransactions) FROM HISTTRN WHERE transactionType = 105) as levy,
(Select SUM(debitTransactions) FROM HISTTRN WHERE transactionType = 100) as roomRevenue
FROM
HISTTRN
GROUP BY FolioNumber
ORDER BY FolioNumber
Following code does work if I only want one transactionType but I want 3 different transaction types
---working code
SELECT FolioNumber,
SUM(debitTransactions) as gst
FROM HISTTRN
WHERE transactionType = 106
GROUP BY FolioNumber
ORDER BY FolioNumber
Is there a possible way of doing that? Thanks
SELECT FolioNumber,
SUM(case when transactionType = 106 then debitTransactions else 0 end) as gst,
SUM(case when transactionType = 105 then debitTransactions else 0 end) as levy,
SUM(case when transactionType = 100 then debitTransactions else 0 end) as roomRevenue
FROM HISTTRN
GROUP BY FolioNumber
ORDER BY FolioNumber

Calculate the amount using sql case on free product

I have a sales table which contains (product code, quantity, unitprice...) and I want to calculate the amount for each product code but I have some free product in with I want to have the amount to be 0
How can I do it with SQL?
This is the idea of what I'm expecting
CASE
WHEN freegoodline = 0 THEN
AMOUNT = SUM(B.QUANTITYB.UNITPRICEB.VAT1RATE) OVER(partition by B.PRODUCT_CODE, B.sinvoice_code)
ELSE
AMOUNT = 0
END
Use CASE expression to do conditional aggregation :
SELECT productcode,
SUM(CASE WHEN productcode = 'free' THEN 0 ELSE quatity * unitprice END) AS Amount
FROM sales s
GROUP BY productcode;
Typically, if the product is free, then the unit price will be zero or NULL. If that is the case, you simply need:
sum(quantity * unitprice)
No conditional logic is needed.

SQL - Dividing aggregated fields, very new to SQL

I have list of line items from invoices with a field that indicates if a line was delivered or picked up. I need to find a percentage of delivered items from the total number of lines.
SALES_NBR | Total | Deliveryrate
1 = Delivered 0 = picked up from FULFILLMENT.
SELECT SALES_NBR,
COUNT (ITEMS) as Total,
SUM (case when FULFILLMENT = '1' then 1 else 0 end) as delivered,
(SELECT delivered/total) as Deliveryrate
FROM Invoice_table
WHERE STORE IN '0123'
And SALE_DATE >='2020-02-01'
And SALE_DATE <='2020-02-07'
Group By SALES_NBR, Deliveryrate;
My query executes but never finishes for some reason. Is there any easier way to do this? Fulfillment field does not contain any NULL values.
Any help would be appreciated.
I need to find a percentage of delivered items from the total number of lines.
The simplest method is to use avg():
select SALES_NBR,
avg(fulfillment) as delivered_ratio
from Invoice_table
where STORE = '0123' and
SALE_DATE >='2020-02-01' and
SALE_DATE <='2020-02-07'
group by SALES_NBR;
I'm not sure if the group by sales_nbr is needed.
If you want to get a "nice" query, you can use subqueries like this:
select
qry.*,
qry.delivered/qry.total as Deliveryrate
from (
select
SALES_NBR,
count(ITEMS) as Total,
sum(case when FULFILLMENT = '1' then 1 else 0 end) as delivered
from Invoice_table
where STORE IN '0123'
and SALE_DATE >='2020-02-01'
and SALE_DATE <='2020-02-07'
group by SALES_NBR
) qry;
But I think this one, even being ugglier, could perform faster:
select
SALES_NBR,
count(ITEMS) as Total,
sum(case when FULFILLMENT = '1' then 1 else 0 end) as delivered,
sum(case when FULFILLMENT = '1' then 1 else 0 end)/count(ITEMS) as Deliveryrate
from Invoice_table
where STORE IN '0123'
and SALE_DATE >='2020-02-01'
and SALE_DATE <='2020-02-07'
group by SALES_NBR

SQL select grouping and subtract

i have table named source table with data like this :
And i want to do query that subtract row with status plus and minus to be like this group by product name :
How to do that in SQL query? thanks!
Group by the product and then use a conditional SUM()
select product,
sum(case when status = 'plus' then total else 0 end) -
sum(case when status = 'minus' then total else 0 end) as total,
sum(case when status = 'plus' then amount else 0 end) -
sum(case when status = 'minus' then amount else 0 end) as amount
from your_table
group by product
There is another method using join, which works for the particular data you have provided (which has one "plus" and one "minus" row per product):
select tplus.product, (tplus.total - tminus.total) as total,
(tplus.amount - tminus.amount) as amount
from t tplus join
t tminus
on tplus.product = tminus.product and
tplus.status = 'plus' and
tplus.status = 'minus';
Both this and the aggregation query work well for the data you have provided. In other words, there are multiple ways to solve this problem (each has its strengths).
you can query as below:
select product , sum (case when [status] = 'minus' then -Total else Total end) as Total
, sum (case when [status] = 'minus' then -Amount else Amount end) as SumAmount
from yourproduct
group by product

Sql function for statement

I have table below:
Now I need the table like:
Here:If TransType='Deposit' then it need in Debit and if TransType='Withdraw' then it need to be in Credit, And Debit-Credit from first to Last as Statement(Balance). Can you give any solution?
Please ask me for further clarification.
The balance is a bit tricky. The rest is a simple case:
select t.*,
(case when TransType = 'Deposit' then amount end) as credit,
(case when TransType = 'Withdraw' then amount end) as debit,
sum(case when TransType = 'Deposit' then amount
when TransType = 'Withdraw' then - amount
end) over (partition by BankName order by TransDate
) as balance
from t;
As far as I am getting the question you need 2 queries with 'where' clause.
For exemple "Select BankName, TransDate, TransMiti, Description from TableName where TransType = "Deposit""
same goes for WithDraw.
Here is the link to to learn more.
https://www.w3schools.com/sql/sql_where.asp