using CASE WHEN after CTE - sql

I am trying to use CASE WHEN right after CTE definition but the query expects SELECT only:
WITH A AS
(...) --long query here
CASE WHEN #parameter = '' THEN
SELECT * FROM A
ELSE
SELECT * FROM A WHERE field like '%' + #parameter + '%'
END
Is there a way to make this query work, besides using OR statement?

First of all, you are using CASE WHEN wrong. It is supposed to be used to return a single value, not a table, as part of for example a select clause. It is not intended to be used as flow control to run one of two queries. Use IF for that.
Second, you cannot split a CTE from a select, it is part of the same statement. You can't go "Here is a CTE, now run one of two statements from it", that is not how CTE statements are written. You can reuse a CTE multiple times in a select, but is going to run the whole select, not just part of it.
Some alternate ways that can work
You can use an IF around the whole query, and write it out twice. This way only one version of the query actually runs.
IF #parameter = ''
SELECT (your query here)
ELSE
SELECT (your query here) WHERE field like ...
You could use dynamic SQL, build the first part of the query as a string. Then only add on the where clause if needed, then run the resulting SQL.

You can use OR in the WHERE clause:
WITH A AS
(...) --long query here
SELECT *
FROM A
WHERE (field like '%' + #parameter + '%') OR #parameter = '';
If field is never NULL, then this is equivalent to:
WITH A AS
(...) --long query here
SELECT *
FROM A
WHERE field like '%' + #parameter + '%';
(LIKE '%%' matches any non-empty string.)

Related

Using CONTAINS to find items IN a table

I'm trying to write a SP that will allow users to search on multiple name strings, but supports LIKE functionality. For example, the user's input might be a string 'Scorsese, Kaurismaki, Tarkovsky'. I use a split function to turn that string into a table var, with one column, as follows:
part
------
Scorsese
Kaurismaki
Tarkovsky
Then, normally I would return any values from my table matching any of these values in my table var, with an IN statement:
select * from myTable where lastName IN (select * from #myTableVar)
However, this only returns exact matches, and I need to return partial matches. I'm looking for something like this, but that would actually compile:
select * from myTable where CONTAINS(lastName, select * from #myTableVar)
I've found other questions where it's made clear that you can't combine LIKE and IN, and it's recommended to use CONTAINS. My specific question is, is it possible to combine CONTAINS with a table list of values, as above? If so, what would that syntax look like? If not, any other workarounds to achieve my goal?
I'm using SQL Server 2016, if it makes any difference.
You can use EXISTS
SELECT * FROM myTable M
WHERE
EXISTS( SELECT * FROM #myTableVar V WHERE M.lastName like '%'+ V.part +'%' )
Can your parser built the entire statement? Will that get you what you want?
select *
from myTable
where CONTAINS
(lastName,
'"Scorsese" OR "Kaurismaki" OR "Tarkovsky"'
)
This can be done using CHARINDEX function combined with EXISTS:
select *
from myTable mt
where exists(select 1 from #myTableVar
where charindex(mt.lastName, part) > 0
or charindex(part, mt.lastName) > 0)
You might want to omit one of the conditions in the inner query, but I think this is what you want.

How do we match the special character(s) in sybase using like?

How do we match the special character(s) in sybase using like?
I'm using the like condition as a filter to any characters user inputted. Currently using the sybase database. I was able to retrieved some results by inputting some words, But if the user input some special characters like square bracket. It doesn't return any result but when I check the database I can see the square bracket or any special characters in the database.
Sample Data: column searchField : [IAN]Stackoverflow
Declare #value varchar(50)
SET #value = '[IAN]Stackoverflow'
SELECT * FROM Table1 WHERE searchField LIKE '%#value%
I think what you're asking would be solved by:
SELECT * FROM Table1 WHERE searchField LIKE '%' + #value + '%'
You can even have the variable part of the LIKE expression from a table, if you have more than one constant section in a list of values to compare:
SELECT t.*
FROM Table1 t, #surnames s
WHERE t.searchField LIKE '%' + s.surname + '%'
or something like that.

SQL: How To Conditionally Adjust the WHERE Clause Depending on Passed Parameters and still work with UNION

I'm fairly inexperienced with SQL. I'm using SQL Server 2012.
Basically I want the WHERE clause of a SQL SELECT statement to be adjusted depending on the values of certain parameters passed to the stored procedure.
I'll also be UNIONing the result of this SELECT with another SELECT statement within the stored procedure.
The structure so far is as follows:
CREATE PROCEDURE dbo.procMyProcedure
#Param1 smallint = null
, #Param2 int = null
, ...
AS ...
--I have three separate SELECT statements, each catering for a specific scenario
SELECT ...
FROM ...
WHERE
(ER.EMR_Number = ISNULL(#Param1, ER.EMR_Number)) AND
(EE.EME_Number = ISNULL(#Param2, EE.EME_Number))
SELECT ...
FROM ...
WHERE
(EE.EME_Number = ISNULL(#Param2, EE.EME_Number))
SELECT ...
FROM ...
WHERE
(ER.EMR_Number = ISNULL(#Param1, ER.EMR_Number))
The statements are identical except for the WHERE clause. In my scenario, the first statement returns exactly 1 result. The second returns 119 results. The third returns 3 results.
I don't want to run all three statements. I want to merge them into one statement, with that single statement returning the same results as the three statements above, depending on the values of the passed (optional) parameters.
I can do this by wrapping the SELECTs in a nested IF ... ELSE IF structure, but then I can't use UNION. The following structure doesn't work:
IF ...
SELECT ...
ELSE IF ...
SELECT ...
ELSE IF ...
SELECT ...
UNION
SELECT ...
There must be a way to merge these into a single SELECT statement, in such a way that I can use it as part of a UNION statement.
I want to get to the following:
SELECT ... --This select
UNION
SELECT ... --Other stuff
I'd really appreciate any help with this.
Regards,
Adam.
OK. I've figured a solution to my problem. It involves some Boolean logic and some use of NULL and a fair number of brackets.
Here's the WHERE clause I was looking for:
WHERE
((ER.EMR_Number = ISNULL(#Param1, ER.EMR_Number)) AND
(EE.EME_Number = ISNULL(#Param2, EE.EME_Number)))
OR
((ER.EMR_Number = ISNULL(#Param1, NULL)) AND
(EE.EME_Number = ISNULL(#Param2, EE.EME_Number)))
OR
((ER.EMR_Number = ISNULL(#Param1, ER.EMR_Number)) AND
(EE.EME_Number = ISNULL(#Param2, NULL)))
It gives me the exact results I expected, AND I can still use the query in a UNION statement.
Of course, there may be a more elegant solution. If so, please post.
-Adam.
if the emr_number and eme_number are not nullable, just run the first query with an OR instead of an AND

Sql Server IN Clause Issue

Writing a stored procedure that will have multiple input parameters. The parameters may not always have values and could be empty. But since the possibility exists that each parameter may contain values I have to include the criterion that utilizing those parameters in the query.
My query looks something like this:
SELECT DISTINCT COUNT(*) AS SRM
FROM table p
WHERE p.gender IN (SELECT * FROM Fn_SplitParms(#gender)) AND
p.ethnicity IN (SELECT * FROM Fn_SplitParms(#race)) AND
p.marital_status IN (SELECT * FROM Fn_SplitParms(#maritalstatus))
So my problem is if #gender is empty(' ') the query will return data where gender field is empty when I really want to just ignore p.gender all together. I don't want to have to accomplish this task using IF/ELSE conditional statements because they would be too numerous.
Is there any way to use CASE with IN for this scenario? OR
Is there other logic that I'm just not comprehending that will solve this?
Having trouble finding something that works well...
Thanks!
Use or:
SELECT DISTINCT COUNT(*) AS SRM
FROM table p
WHERE
(p.gender IN (SELECT * FROM Fn_SplitParms(#gender)) OR #gender = '')
AND (p.ethnicity IN (SELECT * FROM Fn_SplitParms(#race)) OR #race = '')
AND (p.marital_status IN (SELECT * FROM Fn_SplitParms(#maritalstatus)) OR #maritalstatus = '')
You might also want to consider table-valued parameters (if using SQL Server 2008 and up) - these can sometimes make the code simpler, since they are treated as tables (which in your case, may be empty) and you can join - plus no awkward split function required.

TSQL - ISNULL over multiple columns

I have a simple SQL query (SQL Server 2005) where I'm selecting from a table that contains multiple columns that have BIT values.
These columns are nullable so can contain NULL, 0 or 1.
There are a fair number of these columns and in my query I want to return zero if the value is NULL.
I'm currently using ISNULL like so:
SELECT Name, Age, ISNULL(LikesOranges,0), ISNULL(LikesApples,0), ISNULL(LikesPears,0)
FROM FoodPreferences
As I've mentioned, there are a lot of these BIT columns (much more than in the simple example above).
Is there a way I can use ISNULL over multiple columns like this:
SELECT ISNULL(*,0) FROM FoodPreferences
The above query doesn't work but you get what I'm trying to do - so I can avoid having to write an ISNULL statement for each column,
Thanks.
Try this:
SELECT COALESCE(LikesOranges, LikesApples, LikesPears) AS MyBit FROM FoodPreferences
This will return the first non-null value. If all fields are NULL the result is NULL.
UPDATE:
And the conclusion is:
SELECT ISNULL(COALESCE(LikesOranges, LikesApples, LikesPears),0) AS MyBit FROM FoodPreferences
so I can avoid having to write an
ISNULL statement for each column,
Run this query and copy the result to your select statement. system_type_id = 104 filters the result on bit columns.
select stuff((select ', isnull('+name+', 0)'
from sys.columns
where object_id = object_id('FoodPreferences') and
system_type_id = 104
for xml path('')), 1, 1, '')
Result:
-------------------------------------------------------------------------
isnull(LikesOranges, 0), isnull(LikesApples, 0), isnull(LikesPears, 0)
I don't think so. But an option might be to create a view onto that table and put all the ISNULL statements in the view. At least then you won't have to do it every time
eg.
CREATE VIEW vwFoodPreferences
AS
SELECT Name,
Age,
ISNULL(LikesOranges,0) AS LikesOranges,
ISNULL(LikesApples,0) AS LikesApples,
ISNULL(LikesPears,0) AS LikesPears
FROM FoodPreferences
Unfortunately, the simple answer is no.
You could write sql dynamically, but whatever happens, the final resulting sql would have to be ISNULL(a,0), ISNULL(b,0), ISNULL(c,0), ISNULL(d,0), etc
i think you can write a simple program and generate select clause by reading all columns and generating the select
while not this :
SELECT COALESCE(LikesOranges, LikesApples, LikesPears, 0) AS MyBit FROM FoodPreferences
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/coalesce-transact-sql?view=sql-server-2017