I want to execute a stored procedure with 4 input parameters:
int A, B, C, D
and need to execute as
A/B - C/D
but I have to handle Null and 0 to avoid divide by zero exception.
I was trying this approach, but that didn't work out:
case when D is null or D = 0
then case when B is null or B=0 then 0
else cast(A/B) end
case when C is null or C=0
case when B is null or B= 0, then 0
else cast( A/B) end
case when A is null or A=0
case when D is null or D= 0, then 0
else cast(C/D) end
case when B is null or B=0
case when D is null or D= 0, then 0
else cast(C/D) end
else cast (A/B - C/D) end as Result
Hmmm . . . I am guessing you really want - C/D if A/B is not well-defined.
If so, you don't need a case expression at all:
(coalesce(A / nullif(B, 0), 0) -
coalesce(C / nullif(D, 0), 0)
) as Result
Here we can use ISNULL function also
CASE WHEN ISNULL(B,0) > 0 THEN A/B ELSE 0 END)
-
(CASE WHEN ISNULL(D,0) > 0 THEN C/D ELSE 0 END)
Related
In my SQL query I have a CASE clause. How can I use the variable name from the CASE in where statment. This is my query
SElECT
a,
b,
CASE
WHEN AVG(CAST([x] as DECIMAL(9,2))) = 0
THEN 0
ELSE AVG(CAST([y] as DECIMAL(9,2))) / AVG(CAST([x] as DECIMAL(9,2)))
END AS z
FROM magic_table
WHERE z > 0
GROUP BY a,b
here I can not grab the z in where clause. But How can I do it ? is there any other way of doing it ?
As Panagiotis Kanavos already commented you cant use column alias in where statement but you can put your whole case statement in HAVING clause like so:
SElECT
a,
b,
CASE
WHEN AVG(CAST([x] as DECIMAL(9,2))) = 0
THEN 0
ELSE AVG(CAST([y] as DECIMAL(9,2))) / AVG(CAST([x] as DECIMAL(9,2)))
END AS z
FROM magic_table
GROUP BY a,b
HAVING CASE
WHEN AVG(CAST([x] as DECIMAL(9,2))) = 0
THEN 0
ELSE AVG(CAST([y] as DECIMAL(9,2))) / AVG(CAST([x] as DECIMAL(9,2)))
END > 0
I would like to ultimately write a query that would return the "truth table" result of various LHS operand RHS logical operations. I would expect to see a final result looking something like
LHS
op
RHS
result
0
>
0
0
0
>
1
0
0
>
Null
Null
1
>
0
1
1
>
1
0
1
>
Null
Null
Null
>
0
Null
Null
>
1
Null
Null
>
Null
Null
0
<=
0
1
0
<=
1
1
0
<=
Null
Null
1
<=
0
0
1
<=
1
1
1
<=
Null
Null
Null
<=
0
Null
Null
<=
1
Null
Null
<=
Null
Null
0
<>
0
0
0
<>
1
1
0
<>
Null
Null
1
<>
0
1
1
<>
1
0
1
<>
Null
Null
Null
<>
0
Null
Null
<>
1
Null
Null
<>
Null
Null
I was initially stymied in this quest by not being able to simply return a True/False or 1/0 from a simple select statement. If, for instance, I wish to return the truth table result (1 or True) of 1>0, I cannot simply
SELECT 1>0, but instead have to do something akin to
SELECT
1 LHS, '>' op, 0 RHS,
CASE WHEN (1>0) -- replace 1>0 with logical check of choice
THEN 1
WHEN NOT (1>0) -- remember to do so here also
THEN 0
ELSE NULL
END result
, or the equivalent IIF statement; both the CASE and IIF solutions would require the equation twice - first directly, then within a NOT negation to check for NULL values as possible returns.
Generalizing this to LHS and RHS, we have
SELECT
A.LHS, A.op, A.RHS,
CASE WHEN (A.LHS>A.RHS) -- replace LHS>RHS with logical check of choice
THEN 1
WHEN NOT (A.LHS>A.RHS) -- remember to do so here also
THEN 0
ELSE NULL
END
FROM
Value_Table A
Setting the operator value is something that I also haven't figured out as the operators themselves have to be (AFAIK) stored as strings, so
SELECT
CASE WHEN (A.LHS A.op A.RHS)
THEN 1
WHEN NOT (A.LHS A.op A.RHS)
THEN 0
ELSE NULL
END
FROM
Value_plus_Op_Table A
obviously won't work.
Doing
SELECT
CASE A.op
WHEN '>'
THEN CASE
WHEN (A.LHS > A.RHS)
THEN 1
WHEN NOT (A.LHS > A.RHS)
THEN 0
ELSE NULL
END
WHEN '<='
THEN CASE
WHEN (A.LHS <= A.RHS)
THEN 1
WHEN NOT (A.LHS <= A.RHS)
THEN 0
ELSE NULL
END END result
FROM
Value_plus_Op_Table A
is not a general solution, as each op code must be changed to the appropriate context on an individual basis.
On this server I DO have access to do sp_executesql, but I can't simply sp_executesql #statement=CAST(A.LHS as NVarchar(50))+' '+A.op+' '+(A.RHS as NVarchar(20)) and expand that in the two places in the code that LHS op RHS appears, but would instead need to build the whole query into a string and execute that; and I'm not sure how I would execute that for a list of operands in a single query.
So, how can this query be generalized to encompass multiple operands and data types?
I would like to add a condition if the row value is null or 0 then 0 else 1.
SELECT CASE WHEN NUM_FRIEND IS NULL AND 0 THEN 0 ELSE 1 END AS friends_column
FROM TABLE
I get the following error:
No matching signature for operator and
As a case expression, the syntax is:
SELECT (CASE WHEN NUM_FRIEND IS NULL OR NUM_FRIEND = 0 THEN 0 ELSE 1 END) AS friends_column
FROM TABLE;
You can simplify this to:
SELECT (CASE WHEN NUM_FRIEND <> 0 THEN 1 ELSE 0 END) AS friends_column
FROM TABLE;
Or, instead of 0 and 1, return a boolean:
SELECT (NUM_FRIEND <> 0) AS friends_column
FROM TABLE;
What is wrong with my case statement below?
If the value is numeric then I want to check if its greater than or equal to 5 and return 1 if true else return 0. Is there any elegant way of doing this?
Below CASE is nested in another CASE
CASE
WHEN(
xyz <> a
AND abc <> 3
AND
CASE
WHEN ISNUMERIC(LEFT(o.RepCode, 1)) = 1 THEN
CASE
WHEN CONVERT(INT, LEFT(o.RepCode, 1)) >= 5 THEN 1
ELSE 0
END
ELSE 0
END
)
THEN 1
ELSE 0
I get the below error on the first CASE after the second AND before WHEN ISNUMERIC()
An expression of non-boolean type specified in a context where a condition is expected.
Missing criteria in your outermost case statement:
CASE
WHEN(
xyz <> a
AND abc <> 3
AND
CASE
WHEN ISNUMERIC(LEFT(o.RepCode, 1)) = 1 THEN
CASE
WHEN CONVERT(INT, LEFT(o.RepCode, 1)) >= 5 THEN 1
ELSE 0
END
ELSE 0
END = ? -- Missing criteria
)
THEN 1
ELSE 0
Edit: Not sure there's an ideal way to format this, but I find the following to be easier to follow:
CASE WHEN ( xyz <> a
AND abc <> 3
AND CASE WHEN ISNUMERIC(LEFT(o.RepCode, 1)) = 1
THEN CASE WHEN CONVERT(INT, LEFT(o.RepCode, 1)) >= 5
THEN 1
ELSE 0
END
ELSE 0
END = ? -- Missing Criteria
)
THEN 1
ELSE 0
END
Is the AND operator in SQL Server equivalent to && or & in C# (or other languages)?
Ie, will it check for second condition if first condition is found to be false?
No, there is no short-circuiting in SQL. For example:
SELECT a, b, c
From T t
WHERE is_numeric(c) = 1 AND cast(c as numeric(10,2)) > 100.00
This may generate an invalid cast error where c is not numeric.
However you can force it to short-circuit by re-writing to use a CASE statement:
SELECT a, b, c
From T t
where
case
when is_numeric(c) = 0 then 0
when cast(c as numeric(10,2)) > 100.00 then 1
else 0
end = 1
In general and with the exception of handling nulls any clause of the form
where <EXPR1> AND <EXPR2> AND <EXP3>
can be written as:
where case
when NOT <EXPR1> then 0
when NOT <EXPR2> then 0
when NOT <EXPR3> then 0
else 1 end = 1
Any expression of the form:
where <EXPR1> OR <EXPR2> OR <EXPR3>
Can be written as:
where case
when <EXPR1> then 1
when <EXPR2> then 1
when <EXPR3> then 1
else 0 end = 1