Dynamic where clause based on variable - sql

I am working on a select statement in SQL and am running into issues trying to create a where clause that includes a case statement or an if else statement. I want to select records based on the value of a variable. If the variable is 'True' then only return records from the select statement where a column is null. If the variable is not 'True' then return all records regardless if that columns is null.
Any tips on how to do this?
Below is a simple example of what i am trying to do:
declare #option1 as varchar(5)
--This can be True or False so to test i just put the Set option below
set #option1 = 'True'
Select a,b,c,d...
from ...
where d = case when #option1 = 'True' then NULL End
This is the part where i do not know what to do. I only need to filter out the records if the variable is 'True' so not sure what to put in the else section of the case.

You can't test for d = NULL as your CASE statement does because that will always return false since NULL is not equal to NULL (unless you set ANSI_NULLS to 'off').
The simplest thing to do would be to change the WHERE clause to this:
WHERE #option1 = 'False' OR d IS NULL
If you prefer to use a CASE statement for some reason, you can write it like this:
WHERE 1 = CASE WHEN #option1 = 'False' THEN 1
WHEN #option1 = 'True' AND d IS NULL THEN 1
ELSE 0
END

This:
UPDATE: PinnyM has straightened me out on this. I am leaving my embarrassing logically flawed argument here for the education of the masses. The solution I propose below after "Try this" is certainly still valid, but PinnyM's solutions is by far more elegant and should be used.
WHERE #option1 = 'False' OR d IS NULL
Will always return all the results given his current select statement (assuming #Option1 is simply a flag parameter passed in).
Try this:
SELECT a, b, c, d
WHERE
-- Returns only rows where d is null (if #Option1 is True)
(#Option1 = 'True' AND d IS NULL)
OR
-- returns all the rows (if #Option1 is False)
(#Option1 = 'False')

Related

How to handle NULL values in WHERE clause and change target column based upon its encounter

I need the WHERE clause to change what column it is evaluating when NULL is encountered. For instance I'm trying to do something like this:
SELECT *
FROM customer c
WHERE CASE WHEN c.cust_id_1(#variable) IS NOT NULL THEN c.cust_id_1 = #variable
ELSE CASE WHEN c.cust_id_2(#variable) IS NOT NULL THEN c.cust_id_2 = #variable
ELSE c.cust_id_3 = #variable
Is something like this possible? One of the 3 cust_id's will not be NULL.
That seems like less than optimal table design, but isn't a simple COALESCE where you're after?
WHERE #variable = COALESCE(cust_id_1, cust_id_2, cust_id_3);
You don't need a CASE expression for this, you just need logical operators
SELECT *
FROM customer c
WHERE
(c.cust_id_1 IS NOT NULL AND c.cust_id_1 = #variable)
OR
(c.cust_id_2 IS NOT NULL AND c.cust_id_2 = #variable)
OR
(c.cust_id_3 IS NOT NULL AND c.cust_id_3 = #variable)

Case statement in where clause using not like and is not null

I'm pulling data from an existing table using a stored procedure that has some yes or no choices that the user picks on the front end through a checkbox. I want to limit writing a bunch of different If statements for every choice they make.
This portion of my where clause works. Data is either Y or N for this column.
Where... and IsSigned = Case When #IncludeSigned = 'Y' then IsSigned else 'N' end
I would like to add to the where using is not null and not like if this is possible between the square brackets. So far I have
and SignatureType = case when #IncludeElectronic = 'Y' then Type else [NOT like electronic] end
also
and ReviewDate = Case When #HasReviewDate = 'Y' then [ReviewDate is not null] else null end
This may help you use AND/OR instead of case
where (ReviewDate is not null or #HasReviewDate = 'Y' ) And (....)
ie when #HasReviewDate = 'Y' query will return the records with ReviewDate is not null
and when #HasReviewDate != 'Y' then query will return the records with ReviewDate is null
think of it this way:-
Your first case statement has two possible results:-
IsSigned = 'Y'
IsSigned = 'N'
Your subsequent ones have problems as they don't make sense syntactically. So the second one as written returns
SignatureType = Type
SignatureType = [NOT like electronic]
and your third:
ReviewDate = [ReviewDate is not null]
ReviewDate = null end
SO the operator has to be before the case statement and apply to all of the results of the case statement.
For example
WHERE myfield not like CASE WHEN thatfield=1 THEN 'Fish' ELSE 'Chips END
would produce either
myfield not like 'Fish'
myfield not like 'Chips'
I believe you can not use in this way, apart of that, the impact that is not like can have inside your query can be high, my recommendation changes the strategy that you are using.

Problem with field not equal to null in case statement

So I have EXISTS in huge query which looks like this:
EXISTS(
SELECT
*
FROM
ExistTable
WHERE
ExTableFieldA = #SomeGuid AND
ExTableFieldB = MainTableFieldB AND
ExTableFieldA <> (
CASE
WHEN MainTableFieldZ = 10 THEN MainTableFieldYYY
ELSE NULL
END
)
)
The problem comes from ELSE part of CASE statement, this ExTableFieldA <> NULL will be always false. I could easily write another parameter #EmptyGuid and make it equal to '00000000-0000-0000-0000-000000000000' and everything will work but is this the best approach ?
Pretty much I want to execute another check into the exist for the small size of the records which return the "main" query.
How about removing the case and just using boolean logic?
WHERE ExTableFieldA = #SomeGuid AND
ExTableFieldB = MainTableFieldB AND
(MainTableFieldZ <> 10 OR ExTableFieldA <> MainTableFieldYYY)
I would also recommend that you qualify the column names by including the table alias.
Note: This does assume that MainTableFieldZ is not NULL. If that is a possibility than that logic can easily be incorporated.
ELSE NULL is implied even if you don't list it, but you could use ISNULL here.
ISNULL(ExTableFieldA,'') <> (
CASE
WHEN MainTableFieldZ = 10 THEN MainTableFieldYYY
ELSE ''
END
)
You may need to use some other value like 9999 instead of ''

NULL IN (1,2,NULL) returns false

Why does this SQL-statement return 0?
SELECT CASE WHEN NULL IN (9,1,NULL) THEN 1 ELSE 0 END
SQL is based on three-valued logic, where there are three truth values: TRUE, FALSE, and UNKNOWN. The special NULL value is a placeholder for "missing data" and if you compare something, anything, with missing data the result is unknown.
For example, is <missing data> equal to <missing data>? It's impossible to know, so the result is UNKNOWN.
In this particular case, you are trying to find out if <missing data> is in a given list: since the data is missing, it's impossible to know if it's in the list, and the query returns 0.
SELECT CASE WHEN NULL IN (9,1,NULL) THEN 1 ELSE 0 END
I don't know what RDBMS you are using since some of them has configuration on how NULL will be treated.
NULL IN (9, 1, NULL)
can be written as
(NULL = 9) OR (NULL = 1) OR (NULL = NULL)
and not of them were TRUE nor FALSE. They are all NULL. Since there are only two paths in the CASE statement, it falls under ELSE block.
It depends on how NULL is treated in the specific server.
For instance in SQL SERVER you may set ANSI_NULLS off and have it return 1:
SET ANSI_NULLS OFF
SELECT CASE WHEN NULL IN (9,1,NULL) THEN 1 ELSE 0 END
For further info you should read the remarks section of SET ANSI_NULLS
Because you can't compare null values using comparison operators. You can only use is null or is not null or using functions like COALESCE(), ISNULL(). For example
SELECT CASE WHEN COALESCE(NULL,-1) IN (9,1,-1) THEN 1 ELSE 0 END
Null mean not defined.
NUll object is not equal to other NULL
NULL==1 return false
NUll==2 return false
NULL==NULL return also false

Oracle no results, small query

I am having trouble with some sql. When I run the following query:
Select * from teleapp;
I get TONS of results. Resulst which include a column (called cashwithappyn) that has TONS of empty or null data cells. (They look empty and don't say null)
The column info is:
ColumnName ID Null? Data Type Histogram Num Distinct Num Nulls Density
CASHWITHAPPYN 54 Y VARCHAR2(1 Byte) Frequency 2 56895 0
When I try to run the following query:
Select * from teleapp where cashwithappyn = null;
or
Select * from teleapp where cashwithappyn = '';
or
Select * from teleapp where cashwithappyn not like '';
or
Select * from teleapp where cashwithappyn not in ('Y','N');
or ANY type of combination, I cannot seem to get all of the rows with nothing in cashwithappyn.
Any ideas? Please help, this is the last part of a project that I was assigned to do and I just need to figure this out.
Thanks.
Maybe the column contains blanks. In that case you can do
WHERE TRIM(CASHWITHAPYYN) IS NULL
TRIM removes all blanks before and after and if nothing is left anymore the value becomes NULL
e.g.
TRIM(' ') IS NULL -- one blank removed = true
TRIM(NULL) IS NULL -- true
Also NULL cannot be compared with = NULL but must be phrased IS NULL. NULL is not a value as such and that is why the comparison never works.
You need to use IS NULL
Select * from teleapp where cashwithappyn is null;
Logical test expressions (=, Not In, Like etc) with null result in a false so all of the following result in false
1 = NULL
1 <> NULL
NULL = NULL
NULL <> NULL
NULL NOT IN ('a','b')
NULL Not Like NULL
Additionally in oracle the zero length string is null so NOT LIKE '' will never return any rows
You'll need to use either is null, is not null or Coalesce
A co-worker and I did a bunch of research, here's what we came up with that will work. Any ideas why this works but not the others?
Select * from teleapp where nvl(cashwithappyn,'U') = 'U';