how to take all values from sql table column on condition? - sql

I want to select all column values irrespective of NULL as column value
my problem is when i try to select values using IS NULL i'm getting such records also thise having NULL as a value :(
declare #status varchar(50)=NULL
declare #path varchar(50)= 'India'
select
*
from [vwMYDATA]
where
Path like '%' + #path + '%' and
(Status = #status or #status IS NULL)
vwMYDATA
path status
INDIA1 NULL
INDIA2 close
INDIA3 open
If i execute above query i'm getting all records whose status column has NULL value
expected is if no status value specified show all status records
path status
INDIA1 NULL
INDIA2 close
INDIA3 open
it is showing
path status
INDIA1 NULL
I'm passing these 2 parameters to stored procedure which is having this select statment.
please help me to filtered out and show all the records if status is not given as input

select
*
from [vwMYDATA]
where
Path like '%' + #path + '%' and
((#status IS NULL )OR (Status = #status or status IS NULL))

You need to change the WHERE clause to a Case statement if you want different actions based on whether the #status varchar is NULL.
Select *
From [vwMYDATA]
Where
Path Like Concat('%', #path, '%') And
1 = (
Case When #status Is Null Then 1
When Status = #status Then 1
Else 0
)
This might be inefficient and nonperformant. For performance, it would be better to have a completely different query that matches based on NULL or not, so that proper indexing can be applied.

If you're happy to always filter out records with a null status (which it seems you are) then this should work:
declare #status varchar(50)=NULL
declare #path varchar(50)= 'India'
select
*
from [vwMYDATA]
where
Path like '%' + #path + '%' and
(Status = #status or #status IS NULL)
AND Status IS NOT NULL

Just try remove or #status IS NULL condition
select
*
from [vwMYDATA]
where
Path like '%' + #path + '%' and
(Status = #status)

You need to change your condition like below:
declare #status varchar(50)=NULL
declare #path varchar(50)= 'India'
select
*
from [vwMYDATA]
where
Path like '%' + #path + '%' and
(#status IS NULL OR Status = #status)
you just need to change the place of condition because the conditions check from first, so now if the #status will be null, query don't check next condition.

Get NUll Value Records on Status
select * from vwMYDATA where status is null
Get Not NUll Value Records on Status
select * from vwMYDATA where status is not null

Related

Stored procedure ignoring Nulls and fetch result for only entered parameters

I am creating a stored procedure to do a search through a table. I have many different search columns, all of which are optional. Is there a way to create a stored procedure that will handle this? Let's say I have a table with four columns ID, N1, N2 and N3. I could do something like this:
Table:
INSERT INTO [dbo].[Sample]
VALUES ('1', 'A,B,C', 'A,B,C', 'A,B,C'),
('2', 'B,D,N', 'B,D,N', 'B,D,N'),
('3', 'A,N,S', 'A,N,S', 'A,N,S'),
('4', 'S,F,G', 'S,F,G', 'S,F,G'),
('5', 'D,F,K', 'D,F,K', 'D,F,K'),
('6', 'S,H,Y', 'S,H,Y', 'S,H,Y'),
('7', 'Z,B,C', 'Z,B,C', 'Z,B,C')
Stored procedure:
CREATE PROCEDURE dbo.Sample2
#n11 varchar(max) = null,
#n12 varchar(max) = null,
#n21 varchar(max) = null,
#n22 varchar(max) = null,
#n31 varchar(max) = null,
#n32 varchar(max) = null
AS
BEGIN
SELECT COUNT(*)
FROM Sample
WHERE
(#n11 IS NULL OR Sample.N1 LIKE '%' + #n11 + '%'
OR #n12 IS NULL OR Sample.N1 LIKE '%' + #n12 + '%')
AND (#n21 IS NULL OR Sample.N2 LIKE '%' + #n21 + '%'
OR #n22 IS NULL OR Sample.N2 LIKE '%' + #n22 + '%')
AND (#n31 IS NULL OR Sample.N3 LIKE '%' + #n31 + '%'
OR #n32 IS NULL OR Sample.N3 LIKE '%' + #n32 + '%')
END
If user enters #n11 as A and leave the rest, since N1 contains A in 2 rows, output should be 2 but above query is providing 7. If a parameter is not specified, I need that to be ignored and pass the rest to where condition.
I think you need to AND every separate input condition e.g.
SELECT count(*)
FROM [Sample] S
WHERE (#n11 IS NULL OR S.N1 LIKE '%'+#n11+'%')
AND (#n12 IS NULL OR S.N1 LIKE '%'+#n12+'%')
AND (#n21 IS NULL OR S.N2 LIKE '%'+#n21+'%')
AND (#n22 IS NULL OR S.N2 LIKE '%'+#n22+'%')
AND (#n31 IS NULL OR S.N3 LIKE '%'+#n31+'%')
AND (#n32 IS NULL OR S.N3 LIKE '%'+#n32+'%')
Note the alias, which is the best practice way to avoid having to repeat a long table name all over the query.
Try to remove the next conditions from your stored procedure query:
#n12 IS NULL
#n22 IS NULL
#n32 IS NULL
As the above conditions are returning always true while there were sent when calling the procedure.
Stored procedure code after modified:
Alter Procedure dbo.Sample2
#n11 varchar(max) = null,
#n12 varchar(max) = null,
#n21 varchar(max) = null,
#n22 varchar(max) = null,
#n31 varchar(max) = null,
#n32 varchar(max) = null
AS
BEGIN
select count(*)
from Sample
where (#n11 IS NULL OR Sample.N1 LIKE '%'+#n11+'%' OR Sample.N1 LIKE '%'+#n12+'%')
AND (#n21 IS NULL OR Sample.N2 LIKE '%'+#n21+'%' OR Sample.N2 LIKE '%'+#n22+'%')
AND (#n31 IS NULL OR Sample.N3 LIKE '%'+#n31+'%' OR Sample.N3 LIKE '%'+#n32+'%')
END
Now while executing exec dbo.Sample2 #n11 = 'A' the output will be 2 instead of 7
select
sum(iif(N1 like '%'+#N11+'%',1,0)
+ iif(N1 like '%'+#N12+'%',1,0)
+ iif(N2 like '%'+#N21+'%',1,0)
+ iif(N2 like '%'+#N22+'%',1,0)
+ iif(N3 like '%'+#N31+'%',1,0)
+ iif(N3 like '%'+#N32+'%',1,0)
)
from Sample
Any NULL variables will be ignored.

SQL Server - Using CASE statement

I have a SELECT statement with a WHERE clause that I want to dynamically change depending if a parameter is supplied or not.
I can't seem to understand how to use CASE statement in a WHERE clause but this is how I want it to look like using an IF statement.
DECLARE #Gender NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
DECLARE #Status NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
SELECT Name
FROM Person
WHERE
-- first WHERE clause
IF #Gender IS NULL
BEGIN
Gender IS NULL
END
ELSE
BEGIN
Gender = #Gender
END
AND
-- second WHERE clause
IF #Status IS NULL
BEGIN
Status IS NULL
END
ELSE
BEGIN
Status LIKE '%' + #Status + '%'
END
Is it possible to transform this code into a CASE statement?
I think you want:
select p.name
from person p
where ( (#gender is null and gender is null) or gender = #gender) and
( (#status is null and status is null) or status = #status);
Note that this does "null-matching". Often, people want to use NULL to select all records, not just the NULL ones. If that is what you intend, then:
select p.name
from person p
where ( #gender is null or gender = #gender) and
( #status is null or status = #status);
In either situation, case is not needed in the where. As a general rule, don't use case in where -- unless you really need it to control the order of evaluation of expressions.
You can do this:
SELECT Name
FROM Person
WHERE Gender = COALESCE(#gender, Gender)
AND (#Status is null or Status like '%' + #status + '%')
DECLARE #Gender NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
DECLARE #Status NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
SELECT Name
FROM Person
WHERE CASE WHEN #Gender IS NULL THEN 1
WHEN #Gender = ISNULL(Gender, '') THEN 1
ELSE 0
END = 1
AND CASE WHEN #Status IS NULL THEN 1
WHEN ISNULL(Status, '') LIKE '%' + #Status + '%' THEN 1
ELSE 0
END = 1

Case Statement in Where Clause NULL case [duplicate]

This question already has answers here:
CASE in WHERE, SQL Server
(5 answers)
Closed 4 years ago.
I'm creating a query (to eventually be used in a stored procedure) with multiple variations on what criteria is entered in a form. Sometimes there can be an entry, sometimes not. Sometimes the data field has a value, sometimes it's NULL.
The fields in my form are NAME, SSN, and DRLICENSE.
DECLARE #name VARCHAR(30);
DECLARE #ssn VARCHAR(10);
DECLARE #drlic VARCHAR(10);
--(if for example, someone enters data in two of the fields like this...)
SET #name = 'SMITH'
SET #drlic = 'D'
(In stored procedure)
SET #name = #name + '%'
SET #ssn = #ssn + '%'
SET #drlic = #drlic + '%'
SELECT
NAME,
SSN,
DRLICENSE
FROM
TABLE
WHERE
NAME LIKE CASE WHEN LEN(#name) > 1 THEN #name ELSE NAME END
AND SSN LIKE CASE WHEN len(#ssn) > 1 THEN #ssn ELSE SSN END
AND DRLICENSE LIKE CASE WHEN LEN(#drlic) > 1 THEN #drlic ELSE DRLICENSE END
The idea behind my case statement is to check the variable for usage and perform a like if the name, ssn, or drlicense are partial entries.
My question is: how do I account for the case of NULL in the table column (i.e. SSN LIKE SSN does not work when SSN is NULL because SSN IS NULL needs to be there).
This isn't going to perform well, especially since you are using LIKE but parentheses are important here
where ((#name is null or name like '%' + #name + '%') or ( name is null))
and ((#ssn is null or ssn like '%' + #ssn + '%') or (ssn is null))
and ((#drlic is null or DRLICENSE like '%' + #drlic + '%') or (DRLICENSE is null))
This will return the NULL values in those columns regardless if a parameter is passed in or not. If you don't want the NULL then just remove the or ( name is null)) section from each line. I wasn't certain from your post.
if length(#foo) <= 1
set #foo = NULL
if length(#bar) <= 1
set #bar = NULL
...
WHERE (#foo is NULL or t.foo = #foo)
AND (#bar is NULL or t.bar like #bar)
OPTION (RECOMPILE)
This should do it:
WHERE (#name IS NULL OR name LIKE #name + '%')
AND (#ssn IS NULL OR ssn LIKE #ssn + '%')
AND (#drlic IS NULL OR drlicense LIKE #drlic + '%')
Note that if, for example, user searched for name = foo then it will return rows that match foo% and not rows that have NULL name.
You can inline adding the wild card to the parameter value and add your null checks inline as well. There is no need for a CASE statement either. For each of the parameter/column values the result returns true if the parameter is null or if the column value is null or if the column value starts with the passed in parameter value.
Where statement:
WHERE (Name IS NULL OR #name IS NULL OR Name LIKE #name + '%')
AND (SSN IS NULL OR #ssn IS NULL OR SSN LIKE #ssn + '%')
AND (DRLICENSE IS NULL OR #drlic IS NULL OR DRLICENSE LIKE #drlic + '%')
The key here is to not do any filtering if the incoming value to use is null or if the column value is null which I assume you do not want filtered on if it is null.
You could use ISNULL() it's very useful in cases like yours.
SELECT
NAME,
SSN,
DRLICENSE
FROM
TABLE
WHERE
ISNULL(NAME,0) LIKE ISNULL(ISNULL(#name, NAME),0)
AND ISNULL(SSN,0) LIKE ISNULL(ISNULL(#ssn, SSN),0)
AND ISNULL(DRLICENSE,0) LIKE ISNULL(ISNULL(#drlic, DRLICENSE),0)
This method will replace the NULL values with the column value if the column value is NULL then both will be set to 0 (which will be 0=0, which will always be true).
If I understand correctly, you want a NULL-safe equality. That is, you want NULL to match NULL and values to match values. So:
where (name = #name or (name is null and #name is null)) and
(ssn = #ssn or (ssn is null and #ssn is null)) and
(drlicense = #drlicense or (drlicense is null and #drlicense is null))
or, an intriguing variant:
where (select count(*)
from (select distinct *
from (values (name, 'name'), (#name, 'name'), (ssn, 'ssn'), (#ssn, 'ssn'), (drlicense, 'drlicense'), (#drlicense, 'drlicense')
v(val, which)
) x
) = 3
This is using group by semantics to combine NULL values.
Or, if you want some obfuscation:
where nullif(name, #name) is null and nullif(#name, name) is null and
nullif(ssn, #ssn) is null and nullif(#ssn, ssn) is null and
nullif(drlicense, #drlicense) is null and nullif(#drlicense, drlicense) is null

Using SQL Server CASE statement in WHERE

I want to select records from a table in a stored procedure. Given parameters can be empty or a string including some keys separated by comma (1, 2, etc)
I want to manage that when a parameter is an empty string, "WHERE" ignore searching.
I'm using this code:
where (CASE when #PatientID <> 0 then ( dental.ID_Sick in (1,2)) else (1=1) end)
Something like that is working in W3School. I mean:
SELECT * FROM Customers
WHERE (case when 1=1 then (Country IN ('Germany', 'France', 'UK')) else 1=1 end);
What is the problem in my query that does not work? SQLServerManagementStudio is giving error on "IN" statement.
Solution:
The best way to handle such optional parameters is to use dynamic SQL and built the query on the fly. Something like....
CREATE PROCEDURE myProc
#Param1 VARCHAR(100) = NULL
,#Param2 VARCHAR(100) = NULL
,#Param3 VARCHAR(100) = NULL
,#ListParam VARCHAR(100) = NULL
--, etc etc...
AS
BEGIN
SET NOCOUNT ON;
Declare #Sql NVARCHAR(MAX);
SET #Sql = N' SELECT *
FROM TableName
WHERE 1 = 1 '
-- add in where clause only if a value was passed to parameter
+ CASE WHEN #Param1 IS NOT NULL THEN
N' AND SomeColumn = #Param1 ' ELSE N'' END
-- add in where clause a different variable
-- only if a value was passed to different parameter
+ CASE WHEN #Param2 IS NOT NULL THEN
N' AND SomeOtherColumn = #Param3 ' ELSE N'' END
-- List Parameter used with IN clause if a value is passed
+ CASE WHEN #ListParam IS NOT NULL THEN
N' AND SomeOtherColumn IN (
SELECT Split.a.value(''.'', ''VARCHAR(100)'') IDs
FROM (
SELECT Cast (''<X>''
+ Replace(#ListParam, '','', ''</X><X>'')
+ ''</X>'' AS XML) AS Data
) AS t CROSS APPLY Data.nodes (''/X'') AS Split(a) '
ELSE N'' END
Exec sp_executesql #sql
, N' #Param1 VARCHAR(100), #Param2 VARCHAR(100) ,#Param3 VARCHAR(100) ,#ListParam VARCHAR(100)'
, #Param1
, #Param2
,#Param3
, #ListParam
END
Problem with Other approach
There is a major issue with this other approach, you write your where clause something like...
WHERE ( ColumnName = #Parameter OR #Parameter IS NULL)
The Two major issues with this approach
1) you cannot force SQL Server to check evaluate an expression first like if #Parameter IS NULL, Sql Server might decide to evaluate first the expression ColumnName = #Parameterso you will have where clause being evaluated even if the variable value is null.
2) SQL Server does not do Short-Circuiting (Like C#), even if it decides to check the #Parameter IS NULL expression first and even if it evaluates to true, SQL Server still may go ahead and evaluating other expression in OR clause.
Therefore stick to Dynamic Sql for queries like this. and happy days.
SQL Server does not have a Bool datatype, so you can't assign or return the result of a comparison as a Bool as you would in other languages. A comparison can only be used with IF-statements or WHERE-clauses, or in the WHEN-part of a CASE...WHEN but not anywhere else.
Your specific example would become this:
SELECT * FROM Customers
WHERE 1=1 OR Country IN ('Germany', 'France', 'UK')
It would be better readable to rewrite your statement as follows:
WHERE #PatientID = 0
OR dental.ID_Sick in (1,2)
Referring to your actual question, I'd advise to read the linked question as provided by B House.
May be this straight way will work for you
IF (#PatientID <> 0)
BEGIN
SELECT * FROM Customers
WHERE Country IN ('Germany', 'France', 'UK')
END
try this:
WHERE 1=(CASE WHEN #PatientID <>0 AND dental.ID_Sick in (1,2) THEN 1
WHEN #PatientID =0 THEN 1
ELSE 0
END)

Simple SQL Query Help

I am building a query for a search in MS SQL 05
i have 4 things the user can select, and i want to use AND logic on it.
but i can't seem to get it to work when NULLs are being passed in.
this is what i have:
ALTER PROCEDURE [dbo].[sp_FindSource]
-- Add the parameters for the stored procedure here
#Code varchar(500),
#ssid varchar(50),
#serialNo varchar(50),
#category decimal(10,5)
as begin
SELECT *
FROM tblSource
WHERE Code IN (
SELECT Value
FROM funcListToTableInt(#Code,',')
)
and SSID LIKE '%' + #ssID + '%'
and serialNo LIKE '%' + #serialNo + '%'
and category = #category
end
NOTE: funcListToTableInt function, parses comma seporated values passed in (it works by itself, if i take the other where statements out)
The above search never returns anything, how can i ignore values if they are passed in black and only query the ones that have something in them? uuggh, it's been killing me.
You just have to wrap some OR #param IS NULL checks around your WHERE conditions:
ALTER PROCEDURE [dbo].[sp_FindSource]
-- Add the parameters for the stored procedure here
#Code varchar(500),
#ssid varchar(50),
#serialNo varchar(50),
#category decimal(10,5)
as begin
SELECT *
FROM tblSource
WHERE (Code IN (SELECT Value FROM funcListToTableInt(#Code,',')) OR #Code IS NULL)
AND (SiteSourceID LIKE '%' + #ssID + '%' OR #ssID IS NULL)
AND (serialNo LIKE '%' + #serialNo + '%' OR #serialNo IS NULL)
AND (category = #category OR #category IS NULL)
end
This looks very strange at first glance, since it is checking the parameters for IS NULL, but it works.
Try adding OR clauses for the nulls. SO for example change 'and category = #category' to 'and ((category = #category) or (category is null)).
Do this for all the items for whiuch you want to have a null imput essectially disable that particular test.
There are two ways:
Way 1, ADD OR Clause: It can kill the performance ....
SELECT *
FROM tblSource
WHERE (Code IN (
SELECT Value
FROM funcListToTableInt(#Code,',')
) OR #Code IS NULL)
and (SiteSourceID LIKE '%' + #ssID + '%' OR #SSID IS NULL)
and (serialNo LIKE '%' + #serialNo + '%' OR #serialNo IS NULL)
and (category = #category OR #category)
Way 2: Conditional logic
Considering you have 4 parameters and each may have a value or may not have a value, So you have 2*2*2*2 , 16 different cases. You can write something like:
IF (#SSID IS NULL AND #Code IS NULL AND #serialNo IS NULL AND #category IS NOT NULL) THEN
-- SEARCH only of category
ELSE IF (#SSID IS NULL AND #Code IS NULL AND #serialNo IS NOT NULL AND #category IS NULL) THEN
-- SEARCH only on Serial Number
.
.
.
.
.
As in SQL Server each If block cache its own plan, it will be more performing but based on parameter and there possible combinations this approach may or may not be desired ...