Stored procedure search parameter in MS SQL - sql-server

I have got the MS SQL stored procedure, which is designed to return the results in XML showing all the applicants who are 'sales'.
There are filters on the page to drill down the results one being a search (sString).
The desired behavior is:
If sString is null, it should return all the results;
If sString is not null, it should make sString to the show the found fields.
The SP does not work as expected: it always returns all the results regardless of sString value.
MS SQL Code of the SP:
WITH OrderedMatches AS
(
SELECT ROW_NUMBER() OVER (ORDER BY MB.Member_Registered DESC) AS RowNumber,
MB.Member_ID,
MB.Member_Name, MB.Member_Mobile, MB.Member_Propertytosell, MB.Member_Propertytosell_Details, MB.Member_ExistingBuytoLet, MB.Member_TalkingPoints,
MB.Member_Registered, MB.Member_Funding, MB.Member_Active, MB.Member_Last_Contacted, MB.Member_Situation
FROM dbo.Member_Base MB INNER JOIN dbo.Member_Criteria MC ON MC.Member_ID = MB.Member_ID
WHERE MB.Member_Active = 1 AND MC.Criteria_Section = 'sales'
AND (
#sType = 'a'
OR (
#sType = 'b' AND MB.Member_Propertytosell = 1
)
OR (
#sType = 'c' AND MB.Member_ExistingBuytoLet = 1
)
)
OR (
MB.Member_Name LIKE '%' + #sString + '%' OR MB.Member_Mobile LIKE '%' + #sString + '%' OR MB.Member_Propertytosell_Details LIKE '%' + #sString + '%'
)
)
SELECT
(
SELECT
OM.Member_ID as "#id",
OM.Member_Name as "#appname",
OM.Member_Mobile as "#contact",
OM.Member_Propertytosell as "#propts",
OM.Member_Propertytosell_Details as "#proptsdetails",
OM.Member_ExistingBuytoLet as "#existingBTL",
OM.Member_TalkingPoints as "#talkingpoints",
OM.Member_Registered as "#registered",
OM.Member_Funding as "#funding",
OM.Member_Active as "#active",
OM.Member_Last_Contacted as "#lastcontact",
OM.Member_Situation as "#situation"
FROM OrderedMatches OM
WHERE OM.RowNumber Between #nstart AND #nend
FOR XML path ('applicant'), TYPE
),
(
SELECT COUNT(*) as "#titems"
FROM OrderedMatches
FOR XML path ('meta')
)
FOR XML PATH ('')
END
I suppose the SP is wrong but cant see at which part exactly.
Does anyone have any suggestions?

It's returning everything because you have OR between your sString condition and the rest of conditions in WHERE. Change your WHERE clause to:
WHERE MB.Member_Active = 1 AND MC.Criteria_Section = 'sales'
AND (
#sType = 'a'
OR (
#sType = 'b' AND MB.Member_Propertytosell = 1
)
OR (
#sType = 'c' AND MB.Member_ExistingBuytoLet = 1
)
)
AND (#sString IS NULL
OR
(
MB.Member_Name LIKE '%' + #sString + '%' OR MB.Member_Mobile LIKE '%' + #sString + '%' OR MB.Member_Propertytosell_Details LIKE '%' + #sString + '%'
)
)

Related

SQL Server Case Statement Query

I am writing a stored procedure which has some parameters and want to write a case statement
in query giving me syntax error. Can you help me how to write case statement?
Select *
FROM table1 ssr
left join table2 sse on ssr.case_nbr=sse.case_nbr
left join table3 m on m.MemberId=sse.memberid
where
(
#searchValue IS NULL Or
concat(last_name, first_name) like '%' + #searchValue + '%'
or mrn like '%' + #searchValue + '%' or FIN like '%' + #searchValue + '%'
)
AND (#searchFirst IS NULL Or first_name like '%' + #searchFirst + '%')
//i want to write a case statement
AND (#statusfilter IS NULL OR
CASE
WHEN CHARINDEX('NEW', #statusfilter) = 0
THEN
(sse.Status in (select splitdata from dbo.fnSplitString(#statusfilter,'|')))
ELSE
(sse.Status is Null OR sse.Status in (select splitdata from dbo.fnSplitString(#statusfilter,'|')))
END
)
You have to return value from the CASE, You can use IIF inside THEN and return 1 or 0 and compare that value.
AND (
#statusfilter IS NULL
OR
1 = CASE
WHEN CHARINDEX('NEW', #statusfilter) = 0
THEN IIF(sse.Status in (select splitdata from dbo.fnSplitString(#statusfilter,'|')), 1, 0)
ELSE IIF((sse.Status is Null OR sse.Status in select splitdata from dbo.fnSplitString(#statusfilter,'|')), 1, 0)
END
)
You can just use normal boolean logic, which after cleaning up becomes this:
AND (
#statusfilter IS NULL OR
(
(
(CHARINDEX('NEW', #statusfilter) > 0 AND sse.Status IS NULL)
)
OR sse.Status in (select splitdata from dbo.fnSplitString(#statusfilter, '|'))
)
)
Note that I strongly recommend you use a Table Valued Parameter instead of a split string.
At the very least, you should use the built-in string splitting function STRING_SPLIT (and I hope you are not on an unsupported version which doesn;t have it).

How can I use LIKE operator instead of IN operator for multiple commas contains string in stored procedure

I just made the stored procedure for search items before the procedure I was doing this all via LINQ in C# e.g
//orders
if (objParam.OrderNumber != null && objParam.OrderNumber.Count > 0)
{
foreach (var orderNumber in objParam.OrderNumber)
{
orderNumbersBuilder.Append(',' + orderNumber.ToString());
}
}
var orderNbrs = orderNumbersBuilder.ToString().Trim(',').Split(',');
//Searching
(objParam.OrderNumber.Count == 0 || orderNbrs.Any(a => i.tblOrderMaster.OrderNumber.Contains(a)))
Now I want to do with the stored procedure. I'm getting the result with IN operator but I want to use LIKE operator e.g
SELECT * FROM tblOrderMaster WHERE TrxNumber LIKE '%' + (SELECT * FROM STRING_SPLIT('1330,1329',',')) + '%'
I've multiple filters so I don't want to use function and subqueries e.g
--Params
#Account NVARCHAR(MAX) = NULL,
#OrderNumber NVARCHAR(MAX) = NULL,
#Carrier NVARCHAR(MAX) = NULL,
#ItemCode NVARCHAR(MAX) = NULL,
#OrderType NVARCHAR(MAX) = NULL,
#PONumber NVARCHAR(MAX) = NULL,
#SONumber NVARCHAR(MAX) = NULL
--columns start
--columns end
--Where condtions
(#ACCOUNT IS NULL OR #Account = '' OR partners.PartnerCode IN (select * from string_split(#ACCOUNT,','))) -- multi select filters started
AND
(#OrderNumber IS NULL OR #OrderNumber = '' OR orderMaster.OrderNumber IN (select * from string_split(#OrderNumber,',')))
AND
(#Carrier IS NULL OR #Carrier = '' OR carrier.Description IN (select * from string_split(#Carrier,',')))
AND
(#ItemCode IS NULL OR #ItemCode = '' OR itemMaster.ItemCode IN (select * from string_split(#ItemCode,',')))
AND
(#OrderType IS NULL OR #OrderType = '' OR orderMaster.OrderType IN (select * from string_split(#OrderType,',')))
AND
(#PONumber IS NULL OR #PONumber = '' OR orderMaster.PONumber IN (select * from string_split(#PONumber,',')))
AND
(#SONumber IS NULL OR #SONumber = '' OR orderMaster.SONumber IN (select * from string_split(#SONumber,',')))
You would need to use subqueries; the fact you don't want to doesn't change this with your current design. Using the query with the literal values you have, it would look like this:
SELECT *
FROM dbo.tblOrderMaster OM
WHERE EXISTS (SELECT 1
FROM STRING_SPLIT('1330,1329', ',') SS
WHERE OM.TrxNumber LIKE '%' + SS.[Value] + '%')
If you really don't want to use subqueries, then use table type parameters and then you can perform a JOIN:
SELECT OM.*
FROM dbo.tblOrderMaster OM
JOIN #YourTableVariable YTV ON OM.TrxNumber LIKE '%' + YTV.SearchValue + '%'

Use variable in WHERE clause

My SQL statement in SQL Server looks like this:
DECLARE #forecastYear AS varchar(5)
SET #forecastYear = '2020'
DECLARE #versionName AS varchar(25)
SET #versionName = '20201113_wk'
DECLARE #currentMonth AS varchar(2)
SET #currentMonth = (SELECT current_fc_month FROM tbl_current_month)
SELECT f.record_id
, u.it_ops_j_level_abbr_nm
, f.owner_nm
, f.unit_cd
, f.tbm_cd
, f.tower_nm
, f.description_txt
, f.comment_txt
, f.cost_pool_nm
, f.glac_nr
, f.glac_nm
, f.initiative_nm
, f.priority_nm
, f.growth_nm
, f.it_vendor_nm
, f.jan_amt
, f.feb_amt
, f.mar_amt
, f.apr_amt
, f.may_amt
, f.jun_amt
, f.jul_amt
, f.aug_amt
, f.sep_amt
, f.oct_amt
, f.nov_amt
, f.dec_amt
FROM tbl_new_forecast f
INNER JOIN tbl_unit_tree u
ON f.unit_cd = u.dept_id
WHERE f.version_nm = #versionName
AND f.status_cd = 'Approved'
AND f.entry_type = 'Forecast'
AND f.forecast_yr_id = #forecastYear
AND ABS(f.nov_amt)+ABS(f.dec_amt) <> 0
What I want to do is change the last statement in the WHERE clause based on the value in #currentMonth.
Therefore, if #currentMonth = '3' then the last statement would read
AND ABS(f.mar_amt)+ABS(f.apr_amt)+ABS(f.may_amt) <> 0
If #currentMonth = '7' then it would read
AND ABS(f.jul_amt)+ABS(f.aug_amt)+ABS(f.sep_amt) <> 0
I'm having a hard time figuring out how to accomplish this, because I get a SQL error with this syntax:
AND CASE
WHEN #currentMonth = '10' THEN ABS(f.oct_amt)+ABS(f.nov_amt)+ABS(f.dec_amt) <> 0
END
Any help is appreciated!
If you need a solution, a complex WHERE clause is an option. Note, that in T-SQL CASE is an expression, not a statement:
AND (
((#currentMonth = 1) AND (ABS(f.jan_amt) + ABS(f.feb_amt) + ABS(f.mar_amt) <> 0)) OR
((#currentMonth = 2) AND (ABS(f.feb_amt) + ABS(f.mar_amt) + ABS(f.apr_amt) <> 0)) OR
...
((#currentMonth = 10) AND (ABS(f.oct_amt) + ABS(f.nov_amt) + ABS(f.dec_amt) <> 0)) OR
((#currentMonth = 11) AND (ABS(f.nov_amt) + ABS(f.dec_amt) <> 0)) OR
((#currentMonth = 12) AND (ABS(f.dec_amt) <> 0))
)
Use dynamic SQL
DECLARE #month_dependent varchar (500)=' ';
DECLARE #main_query varchar(1000)=' ';
DECLARE #forecastYear AS varchar(5)
SET #forecastYear = '2020'
DECLARE #versionName AS varchar(25)
SET #versionName = '20201113_wk'
DECLARE #currentMonth char(2)
SET #currentMonth = (SELECT current_fc_month FROM tbl_current_month)
If #currentMonth = '3'
BEGIN set #month_dependent=' AND ABS(f.mar_amt)+ABS(f.apr_amt)+ABS(f.may_amt) <> 0 '; END
If #currentMonth = '7'
BEGIN set #month_dependent=' AND ABS(f.jul_amt)+ABS(f.aug_amt)+ABS(f.sep_amt) <> 0 '; END
set #main_query varchar(1000)=' SELECT f.record_id' +
' , u.it_ops_j_level_abbr_nm ' +
-- ' and all the rest of it! ' +
' FROM tbl_new_forecast f '+
' INNER JOIN tbl_unit_tree u '+
' ON f.unit_cd = u.dept_id ' +
' WHERE f.version_nm = '''+ #versionName + ''' '+
' AND f.status_cd = ''Approved'' '+
' AND f.entry_type = ''Forecast'' '+
' AND f.forecast_yr_id = ''' + #forecastYear + ''' '+
#month_dependent
EXECUTE sp_executesql #main_query ;
You can make this really complex by using a WHERE clause with a lot of ors in it:
AND ({first month condition} OR {Second month condition} OR {third month condition})
Etc. Another option is to place this into a stored procedure and use the month as the trigger to determine which statement to run. Depending on how you are running this, it might be a preferred method, as it can abstract out the details from the application (something you will want if you ever decide to normalize this data).
As for trying to use CASE in a WHERE clause, you have it wrong. The CASE WHEN has to equal something. The correct syntax is like:
AND SomeValue = CASE WHEN ...
You cannot simply use case, as a where is looking for equality (=), inequality (<>), and fuzzy values (LIKE). Thus, this does not work.
AND CASE WHEN ...
As an example, this shows something that fires back 1 to get equivalent rows. But you would need all of your conditions in here, which means the WHEN on month and the ABS() would be the entire condition. You then return 1 to indicate "found it". But you are running this as a monthly query, so filtering by the month and then determining the CASE ... WHEN is where you go.

Select all data when passing parameters with null

I am using SQL Server 2012. This is my stored procedure code:
select *
from tbl_Events te
where te.MainEventID = ISNULL(#EventID, te.MainEventID)
and te.EventCityID = ISNULL(#CityID, te.EventCityID)
and te.OwnerPassNo = ISNULL(#PassNo, te.OwnerPassNo)
and te.[Owner] LIKE '%' + #Owner + '%'
and te.isActive = 'true'
When I try to execute it with the following
exec sp_GetEvents #Owner=N''
it returns 0 rows, though I have some data in my table.
What am I doing wrong?
Please try:
select * from tbl_Events te
where
(#EventID IS NULL OR te.MainEventID = #EventID) AND
(#CityID IS NULL OR te.EventCityID = #CityID) AND
(#PassNo IS NULL OR te.OwnerPassNo = #PassNo) AND
te.[Owner] like '%' + #Owner + '%' AND
te.isActive = 'true'
And check if 'isActive' expects 'true' or 1

Using And,Or in a sql for multiple results

I have a textbox and 3 dropdown boxes with an item that could be selected in each of the dropdowns. There are two filtering scenarios I want to be able to achieve.
Getting a filtering result after typing a value in the textbox and select values in the next two textboxes leaving out the last one.
Getting a filtering after typing a value in the textbox and select values in the other three dropdown boxes to filter out the result. My code below can only produce each of the results one at a time If I change the "and" to "or" and the "or"s to "and"s. Can anyone help with modification or new query to be able to achieve the two scenarios?
CREATE PROC Spsearchproduct #searchWord1OnMasterPage NVARCHAR (50),
#searchWord2OnMasterPage NVARCHAR (50),
#searchWord3OnMasterPage NVARCHAR (50),
#searchWord4OnMasterPage NVARCHAR (50)
AS
BEGIN
SELECT product.NAME,
price,
seller,
productstreetno.strno,
productstreet.streetname
FROM product
INNER JOIN productstreetno
ON product.streetnoid = productstreetno.idstreetno
INNER JOIN productstreet
ON product.streetid = productstreet.idstreet
INNER JOIN productstate
ON stateid = productstate.idstate
INNER JOIN productcity
ON cityid = productcity.idcity
WHERE product.NAME LIKE '%' + #searchWord1OnMasterPage + '%'
AND productstate.statename LIKE '%' + #searchWord2OnMasterPage + '%'
AND ( ( productcity.cityname LIKE '%' + #searchWord3OnMasterPage + '%' )
OR ( productstreet.streetname LIKE '%' + #searchWord4OnMasterPage + '%' )
OR ( productstreet.streetname IS NULL ) )
AND ( ( productcity.cityname LIKE '%' + #searchWord3OnMasterPage + '%' )
OR ( productstreet.streetname LIKE '%' + #searchWord4OnMasterPage + '%' )
OR ( productstreet.streetname IS NULL ) )
END
Product.Name Like '%' + #searchWord1OnMasterPage + '%' and
ProductState.StateName Like '%' + #searchWord2OnMasterPage + '%' and
(ProductCity.CityName Like '%' + #searchWord3OnMasterPage + '%' )and
((ProductStreet.StreetName Like '%' + #searchWord4OnMasterPage + '%') or
(#searchWord4OnMasterPage = 'Select Street'))

Resources