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