AND and OR operator in SQL Server - sql

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

Related

Logical Values in SQL SELECT clause

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?

How to use case function in SQL where clause?

I am converting a Crystal Report to SSRS. In the CR Select Records section there are several filters including an IF statement like this:
(if BeginCompany <> 0 and EndCompany <> 999 then
Company between BeginCompany and EndCompany else 1 = 1)
How can I make an equivalent CASE statement in an SQL WHERE clause in my dataset? Thanks.
Are BeginCompany and EndCompany actually variables? What are they when you don't want to use them as a filter? NULL? Something else?
Maybe you're looking for this (assuming companies are represented by positive integers):
WHERE Company >= COALESCE(#BeginCompany, 0)
AND Company <= COALESCE(#EndCompany, 2147483647)
Which is just another way to express:
WHERE Company >= CASE
WHEN #BeginCompany IS NULL THEN 0 ELSE #BeginCompany END
AND Company <= CASE
WHEN #EndCompany IS NULL THEN 2147483647 ELSE #EndCompany END
You can't use a CASE expression for control-of-flow, e.g.
CASE ... something ... THEN Column BETWEEN x AND y
CASE is an expression that returns a single value. Much more background here:
Dirty Secrets of the CASE Expression
It sounds like the logic wants the Company field to be between the BeginCompany and EndCompany parameters if BeginCompany <> 0 and EndCompany <> 999 to show a record but if they do equal 0 or 999, then show all records. If a users enters 0 for the Begin parameter or 999 for the end, then the query would show all records.
I think in SQL it would be
WHERE (
#BeginCompany <> 0
and #EndCompany <> 999
AND Company between #BeginCompany and #EndCompany
)
OR (
#BeginCompany = 0
OR
#EndCompany = 999
)
If you really wanted to squeeze a CASE statement if there then
WHERE CASE WHEN
#BeginCompany <> 0
and #EndCompany <> 999
AND Company between #BeginCompany and #EndCompany
THEN 1
WHEN
#BeginCompany = 0
OR
#EndCompany = 999
THEN 1
ELSE 0 END = 1

Bigquery if null and 0 then condition

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;

Use nested case, when and else condition in stored procedure

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)

check if value is numeric in sql view

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