SQL CASE between values of the same table - sql

I have the following #temp table :
SELECT *
FROM #temp
WHERE LinkingID = 1
------------------------------------------------------------------
|Condition_ID LinkingID Operator Variable1 Variable2 |
| 1 1 == 25 2 |
| 2 1 <> 3 7 |
| 3 1 == 4 4 |
------------------------------------------------------------------
I want to implement a CASE ( ??? ) that will check if Variable1 OPERATOR Variable2 is true, make the check for all rows and IF all rows are true then do something, else break off and abort.
I was thinking something like this ( I'm not sure how to express this in T-SQL so I use pseudolanguage ) :
CASE
WHEN Operator LIKE '=='
THEN IF Variable1 == Variable2 THEN TRUE
ELSE THEN FALSE
WHEN Operator LIKE '<>'
THEN IF Variable1 <> Variable2 THEN TRUE
ELSE THEN FALSE
FROM #temp
If the result of this is true for all rows, then do something, else do something else
In the scenario above :
Row1 would return FALSE
Row2 would return TRUE
Row3 would return TRUE
Hence the result is FALSE.

Accumulating comparison results over the whole table
Checking that the whole table returns true for all rows is best done to count false ones and check whether that number is greater equal to 0. If it's 0 then it means that all rows matched otherwise number indicates number of rows that failed
Mind the inverted comparison compared to Operator value to catch negatives:
declare #NonMatched int
select
#NonMatched = sum(
case
when [Operator] = '==' and Variable1 <> Variable2 then 1
when [Operator] = '<>' and Variable1 = Variable2 then 1
else 0
end
)
from #temp
where LinkingID = 1
if #NonMatched = 0
begin
-- execute your stored procedure or whatever else set of statements
end
Here's also a SQLFiddle that's based on upper code.

Im going to go out on a limb and guess you're trying to do something with all rows which the conditional variable 1 [operator] variable2 evaluates true. This could be selecting them, or deleting them - it makes no difference really.
I'll use a select as the example:
SELECT *
FROM #temp
WHERE LinkingID = 1
AND CASE Operator
WHEN '==' THEN Variable1 = Variable2
WHEN '<>' THEN Variable1 <> Variable2
END
The same where clause could be used if you wanted to delete these records.
EDIT To aggregate up this set and do something when all conditions for a particular LinkingID evaluate true, something like this will work:
IF EXISTS(
SELECT LinkingID FROM temp
WHERE LinkingID = 1
GROUP BY LinkingId
HAVING SUM(CASE
WHEN Operator = '==' AND Variable1 = Variable2 THEN 1
WHEN Operator = '<>' AND Variable1 <> Variable2 THEN 1
ELSE 0
END) = count(*)
)
BEGIN
-- Do something
END
Live example to play with here: http://www.sqlfiddle.com/#!6/26d72/6
In that example I have set up LinkingID=2 where all conditions are true. Change the LinkingId=1 to =2 to see the do something message.

I would write something like this:
SELECT
CASE WHEN NOT EXISTS
( SELECT *
FROM #temp
WHERE LinkingID = 1
AND NOT ( Operator = '==' AND Variable1 = Variable2
OR Operator = '<>' AND Variable1 <> Variable2
)
) THEN 'TRUE'
ELSE 'FALSE'
END AS Result ;

Related

SQL - Multiple 'THEN' options in a 'CASE WHEN' statement

I need to use a CASE WHEN statement in my query with multiple 'THEN' options.
So something like this:
...
WHERE
region = CASE WHEN #cbEU = 'true' **THEN 0 OR 1**
ELSE 2 END
Or perhaps something like:
...
WHERE
region IN CASE WHEN #cbEU = 'true' **THEN (0,1)**
ELSE (1,2) END
I don't suppose there is an easy way to do this?
You can use:
WHERE ((#cbEU = 'true') AND region IN (0, 1)) OR
((#cbEU = 'false') AND region IN (1, 2))
Here is the sample code which i wrote to answer your query :
Create Table Test
(
a int,
b varchar(10)
)
Insert into Test Values (1,'Sample1'),(2,'Sample2'),(3,'Sample3'),
(4,'Sample4'),(5,'Sample5')
Declare #input int = 2
SELECT * from Test where
b =
CASE #input
when 1 then 'Sample1'
when 2 then 'Sample2'
when 3 then 'Sample3'
END
Output :
a | b
2 | Sample2
Case statement is pretty useful in scenarios like yours. It can be used in select, update, where , having, OrderBy, Delete statements.
Reference :
http://www.dotnet-tricks.com/Tutorial/sqlserver/1MS1120313-Understanding-Case-Expression-in-SQL-Server-with-Example.html

SQL IF NULL From SELECT statement

Why does this give me 1 which is what I was expecting:
IF (SELECT 123) = 123
PRINT 1
ELSE
PRINT 2
But this gives me 2 which I was not expecting:
IF (SELECT NULL) = NULL
PRINT 1
ELSE
PRINT 2
NULL values are checked by IS NULL
you have to use:
IF (SELECT NULL) IS NULL
PRINT 1
ELSE
PRINT 2
from the manual:
To search for column values that are NULL, you cannot use an expr =
NULL test. The following statement returns no rows, because expr =
NULL is never true for any expression
If you put NULLS OFF
SET ANSI_NULLS OFF
IF (SELECT NULL) = NULL
PRINT 1
ELSE
PRINT 2
then you will get PRINT 1
You cant check NULL with =. For that IS has to be used.
Ex:
IF (SELECT NULL) IS NULL
PRINT 1
ELSE
PRINT 2
You cannot check NULL using =. You need to use IS NULL like the following
IF (SELECT NULL) IS NULL
PRINT 1
ELSE
PRINT 2

select NULL and false but not true in sql

i an new in vb.ner sql and what i am asking may be silly question. I have a table in sql server 2005 and a column name activated. this column contain NULL, true or false.
I want to select only NULL or false values. How can i do this?
The selection should be done on the SQL Server's side. Your query should look like this:
SELECT *
FROM MyTable
WHERE activated = 0 OR activated is NULL
The above assumes that the column activated is of an integral or a BIT data type.
Note: it may be tempting to use a seemingly equivalent WHERE activated <> 1 condition. This would be incorrect, though, because comparisons of NULL values to anything result in a NULL, so the rows with activated = NULL would be excluded.
You should be able to do a coalesce on the field to get it to false if it is null. A coalesce statement checks to see if the first parameter is null, if it is it returns the value in the second parameter. There would be two solutions:
SELECT *
FROM MyTable
WHERE COALESCE(activated,'false') <> 'true'`
--OR--
SELECT *
FROM MyTable
WHERE activated = 'false' or activated is null
With SQL's 3-valued logic, comparisons for NULL need to be done using the IS NULL operator... the check for false can be done with =:
SELECT YourColumn
FROM YourTable
WHERE
YourColumn IS NULL
OR YourColumn = 0
SELECT * FROM MyTable WHERE isnull(activated, 0) = 0
For checking NULL you have to use the keyword "IS NULL" and for false =0 like below
SELECT * FROM MyTable WHERE activated = 0 OR activated is NULL
Sometimes you have to see it to believe...
PRINT '0 = 0' ; IF 0 = 0 PRINT 'true' ELSE PRINT 'false';PRINT '';
PRINT '0 = 1' ; IF 0 = 1 PRINT 'true' ELSE PRINT 'false';PRINT '';
PRINT '0 = NULL' ; IF 0 = NULL PRINT 'true' ELSE PRINT 'false';PRINT '';
PRINT '1 = NULL' ; IF 1 = NULL PRINT 'true' ELSE PRINT 'false';PRINT '';
PRINT 'NULL = NULL' ; IF NULL = NULL PRINT 'true' ELSE PRINT 'false';PRINT '';
PRINT 'NULL IS NULL'; IF NULL IS NULL PRINT 'true' ELSE PRINT 'false';PRINT '';
The SQL way is to use IS TRUE or similar:
SELECT * FROM MyTable WHERE activated = 0 IS NOT FALSE

Return Condition from case statement in where clause

By searching a number of SO threads I am unable to write a query which returns the appropriate condition in the where clause.
For example I have column Col1 which is int and a variable var1 as varchar now I used below query but it is not working.
Where CASE WHEN var1 = '1' THEN (Col1 = 1)
WHEN var1 = '2' THEN (Col1 = 2)
ELSE AND (1= 1)
END
It gives me syntax error near '='.
EDIT:
What If I want condition like
Col1 IN (condtions....)
I think it should be like;
Where Col1 = CASE WHEN var1 IN ('1','2') THEN var1 ELSE Col1 END
OR
Where Col1 = CASE var1 WHEN '1' THEN 1
WHEN '2' THEN 2
ELSE Col1 END ...
As a side note, if Col1 is nullable and need to select those as well then use;
Where Col1 is null OR
Col1 = CASE var1 WHEN '1' THEN 1
WHEN '2' THEN 2
ELSE Col1 END ...
CASE is an expression that returns a value. It is not for control of flow logic like IF (though a similar keyword does work that way in some languages like VB). Try:
WHERE Col1 = CASE
WHEN var1 = '1' THEN 1
WHEN var1 = '2' THEN 2
ELSE Col1
END
This will work as you've intended in the code you've tried unless Col1 is NULLable. One workaround is a magic value that can't appear in your data:
WHERE COALESCE(Col1, -1) = CASE
...
ELSE COALESCE(Col1, -1) END
You need to put the column outside of the case:
where Col1 = case when var1 = '1' then 1
when var1 = '2' then 2
end
OR (var1 != '1' AND var1 != '2')

How to create a ternary condition on a bit field in T-SQL

I have a SQLExpress table that includes a bit field for storing TRUE/FALSE state.
Something like:
+----+---------+
| ID | IsAlive |
+----+---------+
| 1 | 1 |
| 2 | 0 |
| 3 | NULL |
| 4 | 1 |
+----+---------+
Using that table as our example, I want to create one Stored Procedure that will do any one of the following:
Retrieve all records.
Retrieve only the records with IsAlive=1.
Retrieve only the records with IsAlive=0 or NULL.
I am trying to think of how I can create my query without having to write IF/ELSE conditions - It seems to me there is a better/cleaner way than to do something like this:
-- The ternary logic...
-- 0 or NULL retrieves records where IsAlive = 0 or NULL
-- 1 retrieves records where IsAlive = 1
-- Otherwise return all records
-- sproc .....
#IsAlive tinyint = 2 -- Return all records by default
AS
BEGIN
IF(#SentToNTService = 0 OR #SentToNTService = 1)
BEGIN
SELECT *
FROM MyTable
WHERE IsAlive = #IsAlive;
END
ELSE -- Lame redundancy
BEGIN
SELECT *
FROM MyTable
END
END
Is there another way of creating the same results without having to create two different queries as I did above?
2 suggestions of how to do this:
Assuming your variable #isalive is declared as 'bit' as well (which is should be)
SELECT * FROM #t
WHERE #isalive is null or #isalive = coalesce(isalive, 0)
If you want to use a 'bit compare' solution that doesn't require #isalive to be 'bit' (it will work for bit as well as tinyint)
SELECT * FROM #t
WHERE coalesce((1-coalesce(isalive, 0)) ^ #isalive, 1) > 0
Second solution is for nerds like me. Some hardcore people may find it interesting (or at least amusing) as I think it offer the best possible performance (please, someone correct me if i am wrong). It is a powerful solution but hard to read.
This will do what you want:
SELECT *
FROM MyTable
WHERE COALESCE(IsAlive, 0) = COALESCE(#IsAlive, COALESCE(IsAlive, 0))
Based on the value of #IsAlive:
If NULL, then will return everything (because the condition is always true)
If 1, then will return those rows with IsAlive = 1
If 0, then will return those rows with IsAlive = 0 or NULL
COALESCE is a function that returns it's first argument, unless it's NULL, in which case it returns its second argument.
So the LHS returns 0 if IsAlive is NULL or 0 and 1 if IsAlive is 1.
The RHS returns the same when the stored procedure argument #IsAlive is NULL and just returns the #IsAlive argument otherwise.
EDIT:
This assumed that #IsAlive is BIT. In the case of tinyint you can add a case statement:
SELECT *
FROM MyTable
WHERE COALESCE(IsAlive, 0) = CASE #IsAlive
WHEN 0 THEN 0
WHEN 1 THEN 1
ELSE COALESCE(IsAlive, 0)
END
try this:
SELECT * FROM MyTable WHERE ISNULL (IsAlive, 0) = ISNULL (#IsAlive, 0)
UNION
SELECT * FROM MyTable WHERE ISNULL (#IsAlive, 0) > 1
This isnt exact, but pretty close to what you can do:
SELECT *
FROM MyTable
WHERE CASE #IsAlive
WHEN 0 THEN IsAlive = #IsAlive
WHEN 1 THEN IsAlive = #IsAlive
ELSE 1=1 --dummy true value, when null or anything else
END
Something like this should also work.
SELECT *
FROM MyTable
WHERE (#IsAlive = 0 and IsAlive=0)
OR (#IsAlive =1 and IsAlive =1)
OR (#IsAlive is null)