CASE expression returns wrong values during percentage calculation - sql

I am currently working on a supermarket database design where I have to have retrieve the price of the product after discount.
There are 2 types of discount: Direct Discount, Quantity Based Discount. The product will either have percentage discount (eg: 10% off) or amount/cash discount (eg: $5 off)
Currently, my code only works for quantity based discount but not the direct discount (percentage discount) where it will return a wrong value.
select id, product_name, unitPrice,Product.discount_cd,
discount_percentange as 'Discount Percentage' ,
discount_amount as 'Discount Amount',
Promotion_Type.quantity,
case when Product.discount_cd NOT LIKE '%DD' AND discount_percentange IS NOT NULL
THEN (unitPrice*ISNULL(discount_percentange,1))*ISNULL(quantity,1)
when (Promotion_Type.discount_cd NOT LIKE '%QB' AND Promotion_Type.discount_percentange IS NOT NULL)
THEN (unitPrice-(unitPrice*discount_percentange))
ELSE (unitPrice*ISNULL(quantity,1))-(unitPrice*ISNULL(discount_percentange,0))-(ISNULL(discount_amount,0))
END AS reduce
from Product
LEFT JOIN Promotion_Type ON Product.discount_cd=Promotion_Type.discount_cd
Based on the picture attached, reduced price for product P001 and P005 is wrong.
Can I know where is the error? The screenshot of the database table output
database product table

I see multiple issues with your CASE statement.
First, I think you are misusing the % wildcard. It represents any number of any characters at the place it is located. For example, '%DD' means anything as long as the last two characters are 'DD'. Adding the NOT just flips it. Therefore, Product.discount_cd NOT LIKE '%DD' will evaluate true as long as the Product.discount_cd does not end in 'DD', which is all of the codes. When you add in the AND discount_percentage IS NOT NULL, the result is, any record that has a discount_percentage will return with the first THEN statement. This includes P001 and P005.
Second, I think you are misusing the ISNULL() function. It's unnecessary to use it on discount_percentageas you have IS NOT NULL as a criterion. Also, if quantity refers to the product quantity, I do not think you should return a 1 when quantity is null.
Presuming that "DD" stands for "Direct Discount", I don't understand why you have records with a "DD" code and no discount_percentage. That being said, I think the below revised CASE statement will meet your needs.
CASE
WHEN
Product.discount_cd LIKE 'DD%' --Any code beginning with 'DD'
AND discount_percentage IS NOT NULL --Must have discount percentage
THEN (unitPrice * ISNULL(quantity,0)) - (unitPrice * ISNULL(quantity,0) * discount_percentage)
WHEN
Promotion_Type.discount_cd LIKE 'QB%' --Any code beginning with 'QB'
AND discount_amount IS NOT NULL --Must have discount amount
THEN unitPrice * ISNULL(quantity,0) - discount_amount
ELSE 0 --No valid discount
END AS reduce

Check this first condition,
case when Product.discount_cd NOT LIKE '%DD' AND discount_percentange IS NOT NULL
THEN (unitPrice*ISNULL(discount_percentange,1))*ISNULL(quantity,1)
The unit discount amount should be deducted from unitPrice.
case when Product.discount_cd NOT LIKE '%DD' AND discount_percentange IS NOT NULL
THEN (unitPrice-(unitPrice*ISNULL(discount_percentange,1)))*ISNULL(quantity,1)

Related

sql multiplication don't show properly total

There is strange multiplication in the script.
SUM(CAST(PurchLine.[Amount Including VAT] AS decimal(10,2)))
OVER(PARTITION BY PurchLine.[Document No_])AS "TotalAmount"
Finding the Total Amount from above.
TotalAmount * TotalAmount * Discount AS PaymentAmount
Finding the discount and final Payment Amount from the above.
For example I have 24.80 * (24.80*0.015) = 24.42
Instead of that I receive 24.30.
Also for the discount 24.80*0.015 = 49.60 This is not correct again. The correct result would be 0.372
But the strange part this is not working only when TotalAmount is lower than 3 digits. When the Total amount is below 100, always the discount is not correct.
I'm not sure what do I have to make so it would work all the time.
The problem was that the this table with column Discount was imported into the sql server from excel file. For some reason the column Discount was not Decimal.
All the column contain numbers like 0.0015, 0.010 and so on...
When I change the column datatype to decimal(10.4) for Discount everything start working fine.
But here is still the question, why this work for number bigger than 100 and for less than 100 don't work?

SQL query issue with zero discount

I am using the below query to get total amount after a discount.
My issue is when the discount is equal to zero, the total amount becomes zero.
How can I resolve this issue?
SELECT
CAST(SUM(Quantity * UnitPrice * (Discount / 100)) AS varchar(50))
FROM
Stock_Purchase_Details
simple case construct
unitPrice *
case when discount > 0 then (discount / 100)
else 1 end
That's for the code you posted. Normally, a discounted price is
unitPrice * ((100 - discount) / 100)
If you want final amount after discount, you should use
CAST(SUM(Quantity * UnitPrice * (1-(Discount/100)) AS VARCHAR(50))
This will give you the amount after discount. Your current formula gives you the amount discounted, not the amount after discount
Why not check to see if Discount/0 is 0 before doing that, and if it is zero, then don't include it? This can be done via case statements:
CASE
WHEN (Discount/100) = 0 then (logic)
ELSE (other logic)
END
Just one solution, as I am sure there are others.
Just by looking at your query, Discount means percentage discounted, not percent discount. In other words, per your SQL query, if Discount is 60%, it doesn't mean 60% off, but it's 40% off.
I'm assuming that's not what you want, so the correct query should be:
SELECT Cast(SUM(Quantity * UnitPrice * ((100-Discount)/100)) as varchar(50))
from Stock_Purchase_Details

Missing Expression Error when I try to convert the currency type

I want to display the output of total price from my table as 'USD 20.00' or 'EURO 40' for US and Euro respectively.
I tired the following code and got the missing expression error.
How to convert it to the specified format?
The data type of the column 'price' is number.
My code goes here..
select convert(varchar(50),convert(money, coalesce(sum(nvl(CASE
WHEN (typ=27 and l.tyt ='USD') THEN 'USD' + PRICE
WHEN (typ=27 and l.tyt='EURO') THEN 'EURO'+ PRICE
END,0)),0)),1) as Total from transactions;
Thanks in advance!
There are several things wrong with the expression. 1) adding string value ('USD'/'EURO') to numeric value (PRICE), 2) NVL() on different data type, 3) SUM() on a string data. Anyone of these could be the cause of the error.
If the table stores differently denominated prices, you cannot sum them into on row - which one do you want to be in the result (EURO or USD). If you want to have both in two rows, the the following should work (note that in your original statement, the alias l is undefined so this is not likely to work):
SELECT 'USD', Sum(price) as Total
FROM transactions
WHERE typ=27 and tyt ='USD'
UNION ALL
SELECT 'EURO', Sum(price) as Total
FROM transactions
WHERE typ=27 and tyt ='EURO'
or simply
SELECT tyt, Sum(price) as Total
FROM transactions
WHERE typ=27
GROUP BY tyt

How do I perform math in SQL query on certain conditions?

I have a few tables I am querying, Item movement, and price. There are three price levels, regular price, reduced price, and sale price. I am attempting to get a markdown (price that item sold at when on sale minus either the regular or reduced price). My item movement table contains only the price the unit sold at and the price type of that sale. I am currently selecting only the items that sold on the sale price type. Next I have to find out whether the item was on a regular or reduced price, which I determine by looking at my price table. The price table has my regular price and reduced price and if the reduced price is null then it is not currently reduced.
How do I tell SQL that I want a column named "markdown" that is essentially (IF price.tprprice not null AND price.tprenddate > #StartDate give me column (price.baseprice - price.tprprice) * itemmovement.qtysold AS markdown ELSE give me column (price.baseprice - itemmovement.price) * itemmovement.qtysold AS markdown)
I need to return the result of each calculation performed on each row into the same column titled Markdown.
Can anyone tell me how this query should be structured?
case when price.tprprice is not null AND price.tprenddate > #StartDate
then (price.baseprice - price.tprprice) * itemmovement.qtysold
else (price.baseprice - itemmovement.price) * itemmovement.qtysold
end as markdown
You would do it with a case statement which works in most databases.

SQL: Calculate Percentage in new column using another column

I found it hard to describe what I wanted to do in the title, but I will be more specific here.
I have a reasonably long query:
SELECT
/*Amount earned with validation to remove outlying figures*/
Case When SUM(t2.[ActualSalesValue])>=0.01 OR SUM(t2.[ActualSalesValue])<0 Then SUM(t2.[ActualSalesValue]) ELSE 0 END AS 'Amount',
/*Profit earned (is already calculated then input into db, this just pulls that figure*/
SUM(t2.[Profit]) AS 'Profit',
/*Product Type - pulls the product type so that we can sort by product*/
t1.[ucIIProductType] AS 'Product Type',
/*Profit Percentage - This is to calculate the percentage of profit based on the sales price which uses 2 different columns - Case ensures that there are no wild values appearing in the reports as previously experienced*/
Case When SUM(t2.[ActualSalesValue])>=0.01 OR SUM(t2.[ActualSalesValue])<0 THEN (SUM(t2.[Profit])/SUM(t2.[ActualSalesValue])) ELSE 0 END AS 'Profit Percentage',
/*Percentage of Turnover*/
*SUM(t2.[ActualSalesValue])/(Select SUM(t2.[ActualSalesValue]) OVER() FROM [_bvSTTransactionsFull]) AS 'PoT'
/*The join is connect the product type with the profit and the amount*/
FROM [dbo].[StkItem] AS t1
INNER JOIN [dbo].[_bvSTTransactionsFull] AS t2
/*There attirbutes are the links between the tables*/
ON t1.[StockLink]=t2.[AccountLink]
WHERE t2.[TxDate] BETWEEN '1/Aug/2014' AND '31/Aug/2014' AND ISNUMERIC(t2.[Account]) = 1
Group By t1.[ucIIProductType]
The 'Percentage of Turnover' part I am having trouble with - I am trying to calculate the percentage of the Amount based on the total amount - using the same column. So eg: I want to take the Amount value in row 1, then divide it by the total amount of the entire column and then have that value listed in a new column. But I keep getting errors or I Keep getting 1 (because it wants to divide the value by the same value. CAN anyone please advise me on proper syntax for solving this:
/*Percentage of Turnover*/
*SUM(t2.[ActualSalesValue])/(Select SUM(t2.[ActualSalesValue]) OVER() FROM [_bvSTTransactionsFull]) AS 'PoT'
I think you want one of the following:
SUM(t2.[ActualSalesValue])/(Select SUM(t.[ActualSalesValue]) FROM [_bvSTTransactionsFull] t) AS PoT
or:
SUM(t2.[ActualSalesValue])/(SUM(SUM(t2.[ActualSalesValue])) OVER() ) AS PoT
Note: you should use single quotes only for string and date constants, not for column and table names. If you need to escape names, use square braces.