Add condition only if data exists - sql

I want to add a condition to the WHERE clause ONLY if a variable has data.
I tried with the following case statement, but it has a syntax error.
Declare #last_name varchar(10) = null;
Select * from TABLE1
Where FirstName = 'John'
AND CASE WHEN #last_name IS NOT NULL THEN LastName = #last_name

Select * from TABLE1
where FirstName = 'John'
AND (#last_name IS NULL OR LastName = #last_name)

Others have already posted better ways to write the logic you are trying to express, but just in case you need to use the CASE syntax in the future, remember that the syntax requires you to include the word END. This tells SQL where the expression finishes.
This is what a basic CASE expression would look like:
CASE
WHEN MyField = 'MyValue' THEN 'MyResult'
WHEN MyField = 'MyOtherValue' THEN 'MyOtherResult'
ELSE 'NoResult'
END
Any CASE expression must have at least the CASE, WHEN, THEN, and END. The ELSE isn't strictly necessary - just be aware that if you don't include it, then the expression will return a NULL if none of the WHEN conditions are met.

You can try the following:
Declare #last_name varchar(10) = null;
Select * from TABLE1
Where FirstName = 'John'
AND LastName = ISNULL(#last_name, LastName)
You can also replace ISNULL with COALESCE too.

Related

Is there a way to use in or = with a case statement in the where clause in sql?

I have a stored procedure that may or may not get a string list of int ids. When it doesn't get it the value is: ' '. Other wise its something like this: '500,507,908'
I'm trying to use it like this:
select ID as projectTeamId, Employee_ID, Supervisor_ID
from ProjectTeam
where Project_ID = #projectId and IsDeleted = 0 and
ID in (CASE #stringList WHEN '' THEN ID ELSE (SELECT * from TurnListStringIntoTable(#stringList)) END)
to get a result set but it errors out with this code when the string list comes in blank:
An error has occurred while processing Report 'MassReleaseHoursReport':
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I know its an issue where id needs to = id instead of being in id. Any ideas on how I can have the case statement work with #stringList = '' then id = id else id in (SELECT * from TurnListStringIntoTable(#stringList))?
TurnListStringIntoTable returns a table from a string list which in my case is just the project Team ID
I would recommend boolean logic rather than a case expression:
where
Project_ID = #projectId
and IsDeleted = 0
and (
#stringList = ''
or id in (select * from TurnListStringIntoTable(#stringList))
)
Unrelated side note: if you are running SQL Server, as I suspect, and your version is 2016 or higher, you can use built-in function string_split() instead of your customer splitter.
Sure!
All you have to do is use the parameterless flavor of case:
select *
from my_table t
where t.col_1 = case
when #var in (1,2,3) then "foo"
when #var = 4 then "bar"
when #var in (5,6,7) then "baz"
else "bat"
end
One might note that the when expressions are not limited to looking at the same variable in any way. The only requirement is that they have to be a boolean expression. They're evaluated in order top to bottom. The first when clause that evaluates to true wins and it's then value is returned.
If there's no else and evaluation fails to find a match, the result value is null.
Your problem though, is that case expressions
return a single value, and
that value must be of the same type. Can have it returning a string in some cases and a table variable in another.
So... your where clause should look something like this:
where ...
and 'true' = case
when #stringList = '' then 'true'
when ID in ( select *
from TurnListStringIntoTable(#stringList)
) then 'true'
else 'false'
end
You'll probably find, too, that invoking a user-defined function to convert a comma-delimited string into a table variable within the where clause is probably a Bad Idea™ due to the performance impact that that will have.
You'd be better off to move your TurnListStringIntoTable call outside of the select statement, thus:
declare #list = TurnListStringIntoTable(#stringlist)
select ...
from ProjectTeam pt
where . . .
and #stringlist = ''
OR exists ( select * from #list x where x.ID = pt.ID )

SQL Server WHERE clause : column IS NULL or column = parameter value

The code snippet below is what I'm trying to achieve, but I'm having trouble making it work. If the parameter that gets passed into the procedure is null, I want to only return the rows with a WHERE clause IS NULL, but if there is a value, I want to return the rows that are equal to the value passed in. Dynamic SQL seems like it would work, but I'm curious if there's an easier way I'm missing. Thanks in advance.
PARAM:
#id varchar(10) = '123456789'
SELECT *
FROM TABLE T
WHERE
CASE
WHEN #id IS NULL THEN (id IS NULL)
ELSE id = #id
END
The logic you want is:
WHERE (#id IS NULL AND id IS NULL) OR
id = #id
You're trying to use a CASE expression like a Case (Switch) statement. Switches don't exist in T-SQL, and a CASE expression returns a scalar value not a boolean result.
Don't, however, use CASE expressions in the WHERE, use proper Boolean logic:
SELECT *
FROM YourTable YT
WHERE (ID = #ID
OR (ID IS NULL AND #ID IS NULL))

When using CASE inside a WHERE clause, without ELSE, what is meant by NULL?

declare #Name varchar(45)
SELECT
*
FROM
table law
WHERE
--law.emp = case when isnumeric(#Name) = 1 then #Name else null end
law.emp = case when isnumeric(#Name) = 1 then #Name end
or coalesce(law.lname + ', ' + law.fname, '') like '%' + #Name + '%'
My question here is focusing on the CASE statement when it evaluates to something other than a numeric value...
If #Name is anything other than a numerical value, what is really happening? law.emp = null??? If so, it shouldn't return any results anyway, because the proper syntax is something like where law.emp is null, right?
So, just for clarification, my emp column doesn't actually contain any nulls.
I'm just trying to figure out what is really happening to my WHERE statement when #Name evaluates to something not numeric...
What actual evaluation is being done? Is SQL ignoring the condition?
That's kind of what I want: For SQL not to do anything with law.emp unless #Name is numeric. (I have other conditions that will use the #Name variable if it is text.)
The expression:
law.emp = NULL
always returns NULL. In a where clause, this is treated as false, and the row is not included in the result set.
I much prefer an explicit conversion:
law.emp = try_convert(int, #Name)
Or to whatever type emp is.

Bit field in where clause

I have a situation where I want to search for a field in the where clause only if the bit variable is 1 else ignore it.
#Active bit = 0
select * from Foo where firstname = 'xyz' and
if(#active=1)
then search on the Active column else ignore the filtering on the Active column. How can I have that in a simple condition instead of checking each parameter seperately and then building the where clause
Just simple logic will usually suffice:
select * from Foo where firstname = 'xyz' and
(#Active = 0 or Active = <filter condition>)
For general advice about writing code for arbitrary search conditions, you could do worse than read Erland Sommarskog's Dynamic Search Conditions in T-SQL
it seems like Active is the Actual Column as well in your table.
using Case stmt you can make the search efficient as it will use appropriate indexes you may have on this table.
DECLARE #Active BIT=0
SELECT *
FROM Foo
WHERE firstname = 'a'
AND active = CASE WHEN #Active=1 THEN #Active ELSE Active END
How about:
DECLARE #Active bit
if #Active = 1
BEGIN
(select * from Foo where firstname = 'bar' and Active = --condition)
END
else
BEGIN
(select * from Foo where firstname = 'bar')
END
of course, something will have to set the value for #Active somewhere between the declaration and the if...else statement.
you can write this as below
select * from Foo where firstname = 'xyz' and (#isactive=0 or (some conditions))

SQL Statement Match Anything

I use a regex in my SQL statements for an app that look like this
SELECT * FROM table WHERE id = {{REPLACEME}}
However, sometimes I'm not giving a parameter to replace that string with. Is there a way to replace it with something that matches anything. I tried *, but that does not work.
SELECT * FROM table WHERE id = id will match all rows that have non-null id
SELECT * FROM table WHERE id = id OR id IS NULL will match all rows.
id is probably a primary key, so you can probably use the former.
Replace {{REPLACEME}} with
[someValidValueForYouIdType] OR 1=1
I can only describe my solution with an example. The #AllRec is a parameter:
Declare #AllRec bit
set #AllRec = {0|1} --as appropriate
SELECT *
FROM table
WHERE
(
id = {{REPLACEME}}
and #AllRec = 0
) OR (
#AllRec = 1
)
In this solution, if #AllRec is 1 then everything is returned, ignoring the id filter. If #AllRec is zero, then the id filter is applied and you get one row. You should be able to quickly adapt this to your current regex solution.
Using the Regex-Replace option opens you up to SQL Injection attacks.
Assuming your language has support for parameterized queries, try this modified version of Jacob's answer:
SELECT * FROM table WHERE (id = #id OR #id IS NULL)
The catch is that you'll always have to provide the #id value.
SELECT field1, field2
FROM dbo.yourTable
WHERE id = isnull(#var, id)
Not sure what language your using, and this code kind of scares me but...
var statement = "SELECT * FROM table";
If REPLACEME is not empty Then
statement += " WHERE id = {{REPLACEME}}"
End If