How to have 3 conditions to fulfill in CASE WHEN in SQL - sql

I am having difficulty when trying to have 3 conditions to fulfill in CASE WHEN in SQL server. Here is my original script but only return value 0 instead of 1 and 0. My purpose is to check when a customer purchase ITEM_01 with more than or equal to 0.06 AND ITEM_02 with more than or equal to 0.06 THEN return value 1 else 0. Here is my script:
CASE WHEN SUM ( CASE WHEN ITEM_01)='DH' AND (ITEM_02)='DH Classic' THEN NVL
(SALE_OUTLETD.PRE_SALES_QTY * SKU_UOM_CONV.MULTIPLIER,0) + NVL
(SALE_OUTLETD.SALES_QTY * SKU_UOM_CONV.MULTIPLIER, 0) -NVL
(SALE_OUTLETD.FRESH_RTN_QTY *SKU_UOM_CONV.MULTIPLIER, 0) - NVL
(SALE_OUTLETD.OLD_RTN_QTY * SKU_UOM_CONV.MULTIPLIER,0) - NVL
(SALE_OUTLETD.DAMAGED_RTN_QTY *SKU_UOM_CONV.MULTIPLIER, 0) - NVL
(SALE_OUTLETD.WITHDRAWAL_RTN_QTY *SKU_UOM_CONV.MULTIPLIER, 0) ELSE 0 END )
>= 0.06 THEN 1 ELSE 0 END 3_PACK_AND_ABOVE
Please help on this question because I have been stuck for few hours now. Any help would be greatly appreciated!

I am finding your example impossible to read but the basic form of CASE is:
select case WHEN first_boolean THEN first_value
WHEN second_boolean THEN second_value
WHEN third_boolean THEN third_value
...
ELSE default_value
Always try to build things off that model. Nested CASE statements like what you are doing are never fun and tend to be fairly error prone.

Related

Case expression degrading performance in Correlated Sub query

SUM((CASE WHEN ([t2].[__measure__8] > 1) THEN (CASE WHEN [t2].[__measure__8] = 0 THEN NULL ELSE (CAST([t2].[__measure__9] as float) / [t2].[__measure__8]) END) ELSE [t2].[__measure__9] END))
when I use this calculation above Correlated Subquery which has a group by too . Its is taking more than 5 minutes to receive the result set. Moreover, the inner subset of query retrieves in just 4 sec. Am I missing something else?
What is the best way to write this case expression?
Sub case statement looks like unnecessary. You can remove CASE WHEN [t 2].[_ measure _8] = 0
SUM(CASE
WHEN ([t2].[__measure__8] > 1) THEN (CAST([t2].[__measure__9] as float) / [t2].[__measure__8])
ELSE [t2].[__measure__9]
END )
Since you only have 1 condition on your case statement, I suggest to use iif function instead.
sum(
iif([t2].[__measure__8] > 1,
iif([t2].[__measure__8] = 0, null, cast([t2].[__measure__9] as float)/[t2].[__measure__8]),
[t2].[__measure__9])
)
Try to break down your query by using subqueries, remove the sum() first then check the improvements.

How to Return a Value using CASE, DECODE, and/or NVL

I'm having a bit of trouble with this. I need a formula that will give me an actual result regardless of whether or not the values are NULL and/or 0. See the following;
SELECT
[...columns...],
(NVL(SUM(table1.qty_rtnd), 0) + NVL(SUM(table1.qty_defective), 0)) / CASE (NVL(table1.sales, 0)) WHEN 0 THEN 1 END AS six_wk_pct_defective,
[...more columns...]
Values in this particular instance:
table1.qty_rtnd = NULL
table1.qty_defective = 7
table1.sales = 560
If the CASE statement is not in this formula and the divisor is 0, Oracle SQL Developer throws an error back to me telling me I cannot divide by zero. That is fine, but when I try to apply a CASE statement to the dividend portion of this formula, the field in the query result is NULL when it should not be (in this particular case, the math makes it that is should be 0.0125).
What am I doing wrong? How can I use CASE, NVL, DECODE or any other functions to fix this issue?
Thanks,
-Ant
UPDATE:
For those looking for an answer. One was provided by someone which is the following;
SELECT (NVL (qty_rtnd, 0) + NVL (qty_defective, 0)) / NVL (NULLIF (sales, 0), 1) FROM table1
How about
SELECT (NVL (qty_rtnd, 0) + NVL (qty_defective, 0)) / NVL (sales, 1) FROM table1
or
SELECT (NVL (qty_rtnd, 0) + NVL (qty_defective, 0)) / NVL (NULLIF (sales, 0), 1) FROM table1
to safeguard sales=0
It's rather hard to understand what you are asking here since you haven't provided us a test case. You haven't told us, for example, what values the various columns have. You told us that, apparently, the desired result is 0.0125 but without any idea what inputs we're supposed to use, we're a bit blind.
If the only problem is your denominator, I suspect that you want the denominator to be
CASE WHEN NVL( table1.sales, 0 ) = 0
THEN 1
ELSE table1.sales
END
If that guess is not correct, please help us out by posting a reproducible test case.

Clean up SQL Code

I have created a working SQL query but it's ugly. I am using the statement:
CASE WHEN p.Guests is null THEN 0 ELSE p.Guests
About 10 times in some calculations being done in the query and I am wondering if it is possible to do something like:
variable = CASE WHEN p.Guests is null THEN 0 ELSE p.Guests
and then instead of 123 * (CASE WHEN p.Guests is null THEN 0 ELSE p.Guests)
I could do 123 * variable. p.Guests is the number of guests attending an event and it varies based on each row in the query.
So my question is: is there a way to make a variable like this in SQL?
No need for a long-winded case statement when there's
ISNULL(p.Guests, 0)
http://msdn.microsoft.com/en-us/library/ms184325.aspx
You can use ISNULL:
select 123 * ISNULL(p.Guests,0) FROM ...
The ISNULL function will return the first parameter, unless it is null in which case it will return the second parameter.

CASE equivalent of a nested IIF statement

Can anyone please decode the following nested IIF to a CASE statement in SQL.. I know IIF is allowed in SQL Server 2012 but I find it hard to get an easy grasp of a nested IIF logic.. following is my nested IIF statement
IIF(IIF(TABLE_A.Col_1 = 0, TABLE_A.Col_2 + (2*TABLE_A.Col_3), TABLE_A.Col_1)<=.5, 'A', 'B') AS Result
Any help is much appreciated.
This should be the equivalent:
CASE
WHEN
CASE
WHEN TABLE_A.Col_1 = 0
THEN TABLE_A.Col_2 + (2*TABLE_A.Col_3)
ELSE TABLE_A.Col_1
END <= .5
THEN 'A'
ELSE 'B'
END As Result
CASE
WHEN
(CASE
WHEN TABLE_A.Col1= 0
THEN TABLE_A.Col2_2 + (2*TABLE_A.Col3)
ELSE TABLE_A.Col1
END) <=0.5
THEN 'A'
ELSE 'B'
END
AS result
I think this is what it boils down to in one CASE expression:
CASE
WHEN TABLE_A.Col_1 = 0 AND TABLE_A.Col_2 + (2*TABLE_A.Col_3) <= .5 THEN 'A'
WHEN TABLE_A.Col_1 <> 0 AND TABLE_A.Col_1 <= .5 THEN 'A'
ELSE 'B'
END
This is old now, and there are other answers that already work, but for fun it is possible to write this as a functional expression without any CASE statements at all, like this:
char(65 + ceiling(ceiling(COALESCE(NULLIF(TABLE_A.Col_1, 0), TABLE_A.Col_2 + (2*TABLE_A.Col_3))) - .5 / 10000000000000))
There is a very small chance that the functional approach will perform noticeably better on large sets with good indexing.
Here's my proof-of-concept test script:
http://sqlfiddle.com/#!3/a95b3/2

Specify order of (T)SQL execution

I have seen similar questions asked elsewhere on this site, but more in the context of optimization.
I am having an issue with the order of execution of the conditions in a WHERE clause. I have a field which stores codes, most of which are numeric but some of which contain non-numeric characters. I need to do some operations on the numeric codes which will cause errors if attempted on non-numeric strings. I am trying to do something like
WHERE isnumeric(code) = 1
AND CAST(code AS integer) % 2 = 1
Is there any way to make sure that the isnumeric() executes first? If it doesn't, I get an error...
Thanks in advance!
The only place order of evaluation is guaranteed is CASE
WHERE
CASE WHEN isnumeric(code) = 1
THEN CAST(code AS integer) % 2
END = 1
Also just because it passes the isnumeric test doesn't guarantee that it will successfully cast to an integer.
SELECT ISNUMERIC('$') /*Returns 1*/
SELECT CAST('$' AS INTEGER) /*Fails*/
Depending upon your needs you may find these alternatives preferable.
Why not simply do it using LIKE?:
Where Code Not Like '%[^0-9]%'
Btw, either using my solution or using IsNumeric, there are some edge cases which might lead one to using a UDF such as 1,234,567 where IsNumeric will return 1 but Cast will throw an exception.
Why not use a CASE statement to say something like:
WHERE
CASE WHEN isnumeric(code) = 1
THEN CAST(code AS int) % 2 = 1
ELSE /* What ever else if not numeric */ END
You could do it in a case statement in the select clause, then limit by the value in an outer select
select * from (
select
case when isNum = 1 then CAST(code AS integer) % 2 else 0 end as castVal
from (
select
Case when isnumeric(code) = 1 then 1 else 0 end as isNum
from table) t
) t2
where castval = 1