Sql using where condition with case and Like - sql

I have a multiple parameter say #route in report builder.I need #route to be able to pass blank (' ') and when that happens everything is displayed on the result, which would be my default for parameter #route. ( as accomplished by
where route LIKE '%' + (LTRIM(RTRIM(#route))) + '%')
Basically do something like this:
SELECT *
FROM #finalTable ft
WHERE CASE WHEN #route = '' THEN route LIKE '%' + (LTRIM(RTRIM(#route))) + '%'
ELSE route IN (#route)
END
To make things more clear:
#route is a string and say has 200 different values. I basically want to set a default value of ' ' (blank or null) and allow say 10 distinct values for the user to select from. So basically if the user does not select anything ( 'cuz the default is blank or could be null )then he/she still gets the whole result set. So if i restrict the user to only pass single values and ' ' being one of them then where #route LIKE '%' + (LTRIM(RTRIM(#route))) + '%' works but I would like it to be done with multiple values being passed as well. I hope it clarifies things more now!!
Any help is appreciated.. thank you in advance

It's not possible to pass a list of parameters directly to an IN statement unfortunately.
If you want to do that, I'd suggest the easiest way is to send a table-valued parameter containing a list of your IDs. That way you can join against it to get the same effect as the IN query you've suggested.
This won't directly permit you to do your conditional WHERE clause, but what you can then do is check whether the table-valued parameter contains any rows at all and act accordingly - perhaps something like:
DECLARE #Routes IDList;
SELECT *
FROM #finalTable ft
LEFT JOIN #Routes r
ON ft.Route=r.Route
CROSS JOIN (SELECT COUNT(*) AS Recs FROM #Routes) cnt
WHERE
1= CASE WHERE cnt.Recs = 0 THEN 1
ELSE CASE WHEN r.Route IS NULL THEN 0 ELSE 1 END

if your #route is something like '1,5,10'
SELECT *
FROM #finalTable ft
WHERE ',' + #route + ',' LIKE '%,' + ft.route + ',%'

I think the normal approach is someting like:
WHERE route = #route OR #route = ''
Often NULL is used for this purpose instead of an empty string:
WHERE route = #route OR #route IS NULL

Related

SQL Server check if value is substring inside isnull

I have a field in UI interface that passes to a stored procedure a null value (when field is unfilled) or a contract number when it is filled. Substrings of the contract number are accepted as input.
Inside the procedure, I need to filter the results by this parameter.
I need something similar to this:
SELECT * FROM tableName tn
WHERE
tn.ContractNumber LIKE ISNULL('%' + #contractNumber + '%', tn.ContractNumber)
What do you think it is the best approach? Problem is that using a condition like this does not return values.
Simply:
SELECT *
FROM tableName tn
WHERE tn.ContractNumber LIKE '%' + #contractNumber + '%'
OR #contractNumber IS NULL
You are really checking multiple condition, so having them separated reads more intuitive (for most people, anyway).
I assume this is just a sample query, and you are not selecting * in reality...
Another one:
SELECT *
FROM tableName tn
WHERE tn.ContractNumber LIKE '%' + ISNULL(#contractNumber, '%') + '%'

Like Query in SQL taking time

So I've looked around to try to find some posts on this and there are many
Like Query 1 and Like Query 2 but none that address my specific question (that I could find).
I have two tables in which I have around 5000000+ records and I am returning Search result from these tables as :
SELECT A.ContactFirstName, A.ContactLastName
FROM Customer.CustomerDetails AS A WITH (nolock)
WHERE (A.ContactFirstName + ' ' + A.ContactLastName LIKE '%' + 'a' + '%')
UNION
SELECT C.ContactFirstName, C.ContactLastName
FROM Customer.Contacts AS C WITH (nolock)
WHERE (C.ContactFirstName + ' ' + C.ContactLastName LIKE '%' + 'a' + '%')
My problem is it is taking around 1 minute to execute.
For above query I am expecting result like :
Please suggest me the best practice to improve performance. Thanks in advance.
NOTE : No missing Indexes.
when you use "LIKE '%xxx%'" index are not used that why your query is slow i think. When you use "LIKE 'xxx%')" index is used (if an index exist on column of course. >Other proble you do a like on concatenante column, i dont knwo if index is used in this case. And why do a 'xxx' + ' ' + 'yyy' like 'z%', just do 'xxx' like 'z%' its the same. You can try to modify your query like this
SELECT A.ContactFirstName, A.ContactLastName
FROM Customer.CustomerDetails AS A WITH (nolock)
WHERE A.ContactFirstName LIKE '%a%' or A.ContactLastName LIKE '%a%'
UNION
SELECT C.ContactFirstName, C.ContactLastName
FROM Customer.Contacts AS C WITH (nolock)
WHERE C.ContactFirstName LIKE 'a%'
Use Charindex which improves performance of the search ,Here it checks the string to match with first charcter of given search charecter and doesn't search for any more matches.
DECLARE #Search VARCHAR(10)='a'
SELECT A.ContactFirstName, A.ContactLastName
FROM Customer.CustomerDetails AS A WITH (NOLOCK)
WHERE CHARINDEX(#Search,(A.ContactFirstName + ' ' + A.ContactLastName),0)>1

how to compare string in SQL without using LIKE

I am using SQL query shown below to compare AMCcode. But if I compare the AMCcode '1' using LIKE operator it will compare all the entries with AMCcode 1, 10,11,12,13. .. 19, 21,31.... etc. But I want to match the AMCcode only with 1. Please suggest how can I do it. The code is given below :
ISNULL(CONVERT(VARCHAR(10),PM.PA_AMCCode), '') like
(
CASE
WHEN #AMCCode IS NULL THEN '%'
ELSE '%'+#AMCCode+ '%'
END
)
This is part of the code where I need to replace the LIKE operator with any other operator which will give the AMCcode with 1 when I want to search AMCcode of 1, not all 10,11,12..... Please help
I think you are looking for something like this:
where ',' + cast(PM.PA_AMCCode as varchar(255)) + ',' like '%,' + #AMCCodes + ',%'
This includes the delimiters in the comparison.
Note that a better method is to split the string and use a join, something like this:
select t.*
from t cross apply
(select cast(code as int) as code
from dbo.split(#AMCCodes, ',') s(code)
) s
where t.AMCCode = s.code;
This is better because under some circumstances, this version can make use of an index on AMCCode.
If you want to exactly match the value, you don't need to use '%' in your query. You can just use like as below
ISNULL(CONVERT(VARCHAR(10),PM.PA_AMCCode), '') like
(
CASE
WHEN #AMCCode IS NULL THEN '%'
ELSE #AMCCode
END
)
Possibly you can remove case statement and query like
ISNULL(CONVERT(VARCHAR(10),PM.PA_AMCCode), '') like #AMCCode

sql, using a subquery in the like operator

why does this work,
select*
from some_table
WHERE some_column_name like '%i%'
and not this?
select*
from some_table
WHERE
some_column_name like (select ''''+'%' +value +'%' + '''' as val
from [dbo].[fn_Split](' i this is a test testing Chinese undefined',' ')
where idx = 0)
I am trying to search for individual words instead of the whole phrase, the split function above will split the string on space characters and plug the results into a table with two columns, idx and value.
the LIKE operator takes a string for an argument. It cannot be used on a table, which I assume your function returns.
I think what you want to do is JOIN to the function, and then check where LIKE fn.Value:
select *
from some_table t
INNER JOIN (select value as val
from [dbo].[fn_Split](' i this is a test testing Chinese undefined',' ')
where idx = 0) f
ON t.some_column_name like '%'+f.val+'%'
If your subquery is guaranteed to only return one result, you could try putting the modulo symbols around it instead of inside it:
LIKE '%' + (YourSubQuery) + '%'
One possible reason is because you are appending single quotes onto the beginning and end of the string, and none of the values actually store single quotes in the string.
Another reason is might not work is because the subquery returns more than one row or zero rows. The function fn_split() is your own function, so I don't know what it returns. You have a subquery in a context where it can return at most one row and one column. That is called a scalar subquery. If the subquery returns more than one row, you will get an error. If the subquery returns no rows -- for instance, if idx starts counting at 1 rather than 0 -- then it will return NULL which fails the test.
If you want to find a match this way, I would recommend exists:
select t.*
from some_table t
where exists (select 1 as val
from [dbo].[fn_Split](' i this is a test testing Chinese undefined',' ') s
where s.idx = 0 and
t.some_column_name like '%' + value + '%'
);
The results of your sub-query is a literal string. The % symbol isn't seen as a wildcard. Also, does your functions return multiple rows? If so, LIKE operator can only evaluate a single value.
If your functions does return a single value, I would suggest looking into using Dynamic SQL. Something like the following:
DECLARE #SQL VARCHAR(MAX), #WildCard VARCHAR(MAX)
SELECT #WildCard = '%' + value + '%'
FROM [dbo].[fn_Split](' i this is a test testing Chinese undefined',' ')
WHERE idx = 0
SET #SQL = 'SELECT * FROM some_table WHERE some_column_name like ''' + #WildCardWildCard + ''''
EXEC(#SQL)

SQL: building a filter - can this be done without dynamic sql?

This is what i see all the time in a list made by us.
Have to make a filter for 2 columns (i took a shorter example, we have lists with 50 columns, looks the same...)
I was wondering if there's a way to do this somehow different.
What do you guys use to filter records from a table?
/* parameters */
#CostNumber = ...
#Description = ...
/* parameters */
SET #strSQL = '
SELECT [CostLevelId], [CostNumber], [Description]
FROM [CostLevel]
WHERE 1 = 1 ' /* this looks weird, but we'll add the "WHERE" stuff easier */
IF (#CostNumber IS NOT NULL)
BEGIN
SET #strSQL = #strSQL + ' AND [CostNumber] LIKE ''%' + REPLACE(#CostNumber,'''','''''') + '%'' '
END
IF (#Description IS NOT NULL)
BEGIN
SET #strSQL = #strSQL + ' AND [Description] LIKE ''%' + REPLACE(#Description,'''','''''') + '%'' '
END
EXEC (#strSQL)
Why not scrap the dynamic SQL approach?
/* parameters */
#CostNumber = ...
#Description = ...
/* parameters */
SELECT [CostLevelId], [CostNumber], [Description]
FROM [CostLevel]
WHERE [CostNumber] LIKE '%' + #CostNumber + '%'
AND [Description] LIKE '%' + #Description + '%'
Couple things to watch out for - nulls in the #CostNumber and #Description params - you'll have to make sure you convert them to empty strings.
Another thing you'll need to consider is the fact that #Description might contain a % character, and you'll have to escape that for the LIKE to work correctly.
I don't know how to do it when the LIKE operator is involved, when using comparison operators I'm using default values to obtain something like this:
select *
from dbo.SomeTable a
where
(a.IntColumn = #IntColumnValue or #IntColumnValue = -1)
and (a.VarCharColumn = #VarCharValue or #VarCharValue = 'zzz')
This way, if I don't want to apply a particular filter I just set it to the default value (in this example -1 or zzz), so its check always yelds true.
Using the LIKE operator should be something similar, maybe you should set the default value to some sort of string you know will never be found in your data? Something like this?
where (a.VarCharColumn like '%' + #VarCharValue + '%' or #VarCharValue = '§§§TheDefaultValue§§§')
I don't have a way to test this atm, but how about
SELECT [CostLevelId], [CostNumber], [Description]
FROM [CostLevel]
WHERE (#CostNumber IS NOT NULL AND [CostNumber] LIKE ''%' + REPLACE(#CostNumber,'''','''''') + '%'')
OR
(#Description IS NOT NULL AND [Description] LIKE ''%' + REPLACE(#Description,'''','''''') + '%'')
GROUP BY [CostLevelId], [CostNumber], [Description]
Failing that, you could try a UNION instead of OR (and grouping).
You can test to see if the value is null in the query, coupled with your condition and an or statement this allows for optional parameters.
This would work for a like statement.
SELECT [CostLevelId], [CostNumber], [Description]
FROM [CostLevel]
WHERE
(#CostNumber is null or [CostNumber] LIKE '%'+#CostNumber+'%')
and
(#Description is null or [Description] LIKE '%'+#Description+'%')
if its a straight equality comparison you can use coalesce to compare to either the populated variable or, when the variable is null, itself.
SELECT [CostLevelId], [CostNumber], [Description]
FROM [CostLevel]
WHERE
[CostNumber] = coalesce(#CostNumber,[CostNumber])
and
[Description] = coalesce(#Description,[CostNumber])
Keep in mind that this may have an adverse effect on your query plans dependant on which variables are set, table population and database structure etc. You may even find that the dynamic sql approach executes more efficiently than this despite the additional complication in its construction.