Multiple conditions on a where clause column in SQL Server - sql-server

I had written a stored procedure where it needs to execute the where condition based on the parameter values as follows :
alter proc sp_cc_get_grn_details
(
#vendor_id varchar(100) = null,
#po_id int = null,
#invoice_id int = null,
#invoice_from_dt datetime2 = null,
#invoice_to_dt datetime2 = null,
#grn_status int = null
)
AS
BEGIN
SELECT vd.vendor_id,vd.vendor_name,id.po_id,id.invoice_id,id.invoice_amount,id.invoice_date,
CASE
WHEN id.grn_status = 0 THEN 'Pending'
WHEN id.grn_status = 1 THEN 'Completed'
ELSE 'Pending'
END AS grn_status into #Tempres
FROM
vendor_details vd JOIN po_details pd on vd.vendor_id = pd.vendor_id
join invoice_details id on id.po_id = pd.po_id
WHERE
(#vendor_id is null or #vendor_id = '' or vd.vendor_id = #vendor_id) AND
(#po_id is null or #po_id = '' or id.po_id = #po_id) AND
(#invoice_id is null or #invoice_id = '' or id.invoice_id = #invoice_id) and
(id.invoice_date BETWEEN #invoice_from_dt AND #invoice_to_dt)
if(#grn_status = 1)
select * from #Tempres where grn_status = 'Completed';
else if(#grn_status = 2)
select * from #Tempres where grn_status = 'Pending';
else
select * from #Tempres;
drop table #Tempres;
END
The above procedure is working. But what's my need is, Is there any way to make "#grn_status" parameter too in the where clause instead of writing with if & else.

something like this would work
where #grn_Status not in (1, 2) or
grn_status =
case #grn_status
when 1 then 'Completed'
when 2 then 'Pending'
end

Related

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 + '%'

Why doesn't sql query return result when i pass a string to it in where clause?

ALTER PROCEDURE [dbo].[USP-Search-DocumentNumber]
#DocumentNumber varchar(100) = NULL,
#Company_ID varchar(10) = NULL
AS
BEGIN
SET #Company_ID= (REPLACE (#Company_ID, '''', ''))
SELECT SalesID, DocumentNumber AS 'DocumentNumber', CompanyID
FROM Sales
WHERE (DocumentNumber LIKE '%' + #DocumentNumber+ '%'
OR #DocumentNumber IS NULL)
AND DocumentNumber IS NOT NULL
AND ISNULL(Active, 0) = 1
AND ISNULL(IsCommited, 0) = 0
AND ISNULL(IsCancelled, 0) = 0
AND CAST(CompanyID AS varchar(10)) IN (#Company_ID)
END
From the VB.NET code, I am passing
l_objcmd.CommandText = "USP-Search-DocumentNumber"
l_objcmd.CommandType = CommandType.StoredProcedure
'l_objParam = l_objcmd.Parameters.Add("#SalesID", SqlDbType.VarChar)
'l_objParam.Value = IIf(ViewState("SalesID") = "", Nothing, ViewState("SalesID"))
'l_objParam.Direction = ParameterDirection.Input
l_objParam = l_objcmd.Parameters.Add("#DocumentNumber", SqlDbType.VarChar)
l_objParam.Value = IIf(ViewState("DocumentNumber") = "", Nothing, ViewState("DocumentNumber"))
l_objParam.Direction = ParameterDirection.Input
l_objParam = l_objcmd.Parameters.Add("#Company_ID", SqlDbType.VarChar)
l_objParam.Value = IIf(Session("DocumentNumberForm_CompanyID") = "", Nothing, Session("DocumentNumberForm_CompanyID"))
l_objParam.Direction = ParameterDirection.Input
l_ObjDs = v_ObjBREngine.ExecuteProcedure(l_objcmd)
If Not IsNothing(l_ObjDs) And l_ObjDs.Tables(0).Rows.Count > 0 Then
gvFilterData.DataSource = l_ObjDs.Tables(0).DefaultView
gvFilterData.DataBind()
gvFilterData.Columns(0).Visible = True
Else
l_ObjDs.Tables(0).Rows.Add(l_ObjDs.Tables(0).NewRow())
gvFilterData.DataSource = l_ObjDs
gvFilterData.DataBind()
gvFilterData.Columns(0).Visible = False
End If
The #Company_ID is passing as "1,2,3" but doesn't return result but when I put directly this in where it works.
I have tried multiple things with it but doesn't work. Why ? I have even used the IN operator but still issue.
This code most likely does not do what you want:
CAST(CompanyID AS varchar(10)) IN (#Company_ID)
It is exactly equivalent to:
CAST(CompanyID AS varchar(10)) = #Company_ID
So if #Comapny_ID contains '1,2,3', then it only matches another string this exactly the same.
I get the idea that Company_Id contains a list of ids that are presumably comma separated values. If so, you need to do the comparison in some other way. A common method would be:
CAST(CompanyID AS varchar(10)) IN (SELECT s.value FROM string_split(#Company_Id, ',') s)
In older versions, one method is:
CONCAT(',', CompanyID, ',') LIKE CONCAT('%,', #Company_Id, ',%')
There may be other ways to pass a list in as well. This is intended to address what I think the issue is in your code.

SQL Server - WHERE clause with CASE

ALTER PROCEDURE GetVendor_RMA_CreditMemo
(#HasCreditMemoNo INT)
BEGIN
SELECT
*
FROM
(SELECT
CreditMemoNumber,
CASE WHEN CreditMemoNumber != ''
THEN 1
ELSE 0
END AS HasCreditMemoNo
FROM
XYZ) as C
WHERE
(C.HasCreditMemoNo = #HasCreditMemoNo OR #HasCreditMemoNo = -1)
END
CreditMemoNumber is a varchar column
I want to achieve this:
CASE
WHEN #HasCreditMemoNo = 0
THEN -- select all rows with no value in CreditMemoNumber Column,
WHEN #HasCreditMemoNo = 1
THEN -- all rows that has some data,
WHEN #HasCreditMemoNo = -1
THEN -- everything regardless..
You can't do this kind of thing with a CASE.
The correct way to do it is with OR:
WHERE (#HasCreditMemoNo = 0 AND {no value in CreditMemoNumber Column})
OR
(#HasCreditMemoNo = 1 AND {all rows that has some data})
OR
(#HasCreditMemoNo = -1)
Would this work for you? I'm not sure if it would improve your performance. You may be better off writing an if else if else statement and three separate select statements with an index on the CreditMemoNumber column.
ALTER PROCEDURE GetVendor_RMA_CreditMemo(#HasCreditMemoNo int)
BEGIN
select
CreditMemoNumber,
case when CreditMemoNumber != '' then 1 else 0 end as HasCreditMemoNo
from XYZ
where
(#HasCreditMemoNo = 0 and (CreditMemoNumber is null or CreditMemoNumber = ''))
or (#HasCreditMemoNo = 1 and CreditMemoNumber != '')
or (#HasCreditMemoNo = -1)
END

T-SQL problems with optional prompts

I am having problems trying to get the below MPAN and TimePeriodStart to be mandatory parameters and the rest to be optional. However when I run the prompts no results come through. Is there anything I am doing wrong here?
alter procedure task2assigned
(
#MPAN varchar(13),
#TimePeriodStart datetime = null,
#TimePeriodEnd datetime = null,
#BSCValidation varchar(1) = null,
#ReadType varchar(1) = null
)
A
SELECT * FROM TABLES
Here is the whole query, as the problem lies with the parameters:
where a.J0003 = (#MPAN)
and d.J0016 >= DateAdd(mm,-36,#TimePeriodStart)
and (#TimePeriodEnd is null or d.J0016 <= DateAdd(mm,-36,#TimePeriodEnd))
and (#BSCValidation = null or d.J0022 = #BSCValidation)
and (d.J0171 is null or d.J0171 = #ReadType)
Why you suddenly put #BSCValidation = null .. null can not be compared using = sign .... anyway below script might help you
Edit 1: As you asked in comment ..
alter procedure task2assigned
(
#MPAN varchar(13),
#TimePeriodStart datetime = DATEADD(year,3,GETDATE()),
#TimePeriodEnd datetime = GETDATE(),
#BSCValidation varchar(1) = null,
#ReadType varchar(1) = null
)
AS
BEGIN
SELECT * FROM TABLES
WHERE a.J0003 = #MPAN
AND (#TimePeriodStart IS NULL OR d.J0016 >= DateAdd(mm,-36,#TimePeriodStart))
AND (#TimePeriodEnd IS NULL OR d.J0016 <= DateAdd(mm,-36,#TimePeriodEnd))
AND (#BSCValidation IS NULL OR d.J0022 = #BSCValidation)
AND (#ReadType IS NULL OR ISNULL(d.J0171,#ReadType) = #ReadType)
END

Extremely ugly query issue

If anyone can help me on this I would be very excited...I've already spent about 4 hours and cannot find out why T-SQL gives me wrong results and the same query in sql is fine(I mean only #ZipCodeIDS is not null, that's why I put null for the rest of vars in plain sql).
T-SQL Query:
-- validate the reference number pattern
DECLARE #PCodePattern nvarchar(130)
IF #PCode = '' SET #PCode = NULL
IF #PCode IS NOT NULL
BEGIN
IF LTRIM(RTRIM(#PCode)) <> ''
BEGIN
-- filter by pattern
SELECT #PCodePattern = #PCode
END
END -- #PCode
if (#strAddress is not null)
set #strAddress = '%' + #strAddress + '%'
Declare #listofIDS table(zipcodeids int)
delete from #listofIDS
IF #ZipCodeIDS = '' SET #ZipCodeIDS = NULL
IF #ZipCodeIDS IS NOT NULL
BEGIN
IF CHARINDEX(',', #ZipCodeIDS) = 0
BEGIN
insert #listofIDS values(#ZipCodeIDS)
END
ELSE
BEGIN
set #ZipCodeIDS = #ZipCodeIDS + ','
WHILE CHARINDEX(',', #ZipCodeIDS) <> 0
BEGIN
insert #listofIDS values(Left(#ZipCodeIDS, CHARINDEX(',',#ZipCodeIDS) - 1))
SET #ZipCodeIDS = SUBSTRING(#ZipCodeIDS, CHARINDEX(',',#ZipCodeIDS) + 1, LEN(#ZipCodeIDS) - CHARINDEX(',',#ZipCodeIDS))
END
END
END
-- select the property data
INSERT INTO #PropertyDetails (PropertyID, PCode, PropertyStatusID, PropertyStatusName,
PropertyTypeID, PropertyTypeName, ResearchStatusID,
ResearchStatusName, FullAddress, PartialAddress, Address1,
Address2, ZipCodeID, ZipCode, ZipCodeDescription, CityID,
CityName, StateID, StateName, StateCode, NumBedrooms, NumBathrooms,
LivingSquareFeet, LotSquareFeet, YearBuilt, ZillowLink,
AssessorParcelNumber, DateWentREO, DateAppearedOnMLS, IsOnTheMLS,
ZPropertyID, LowestPrice, HighestPrice, AskingPrice, DateTimeRecorded,
RecordedByPersonID, RecordedByPersonName, AssignedToPersonID,
AssignedToPersonName, WatchTag, Latitude, Longitude)
SELECT p.PropertyID, p.PCode, p.PropertyStatusID, ps.Name, p.PropertyTypeID, pt.Name,
p.ResearchStatusID, rs.Name, dbo.GetAddress(p.PropertyID),
dbo.GetPartialAddress(p.PropertyID), p.Address1, p.Address2, p.ZipCodeID, z.Code,
z.Description, p.CityID, c.Name, p.StateID, s.Name, s.Code, p.NumBedrooms,
p.NumBathrooms, p.LivingSquareFeet, p.LotSquareFeet, p.YearBuilt, p.ZillowLink,
p.AssessorParcelNumber, p.DateWentREO, p.DateAppearedOnMLS, p.IsOnTheMLS,
p.ZPropertyID, p.LowestPrice, p.HighestPrice, p.AskingPrice, p.DateTimeRecorded,
p.RecordedByPersonID, dbo.GetDisplayName(p.RecordedByPersonID), p.AssignedToPersonID,
dbo.GetDisplayName(p.AssignedToPersonID), w.WatchTag, p.latitude, p.longitude
FROM Properties p
JOIN cfgPropertyStatuses ps
ON ps.PropertyStatusID = p.PropertyStatusID
JOIN cfgPropertyTypes pt
ON pt.PropertyTypeID = p.PropertyTypeID
JOIN cfgResearchStatuses rs
ON rs.ResearchStatusID = p.ResearchStatusID
JOIN ZipCodes z
ON z.ZipCodeID = p.ZipCodeID
JOIN cfgStates s
ON s.StateID = p.StateID
LEFT JOIN cfgCities c
ON c.CityID = p.CityID
LEFT JOIN Watches w
ON w.PropertyID = p.PropertyID AND w.PersonID = #LoggedInPersonID
WHERE /*
******* missing filter *******
this line should filter the risks by #LoggedInPersonID via role
******************************
AND */(#PropertyID IS NULL OR p.PropertyID = #PropertyID)
AND (#PCodePattern IS NULL OR p.PCode LIKE #PCodePattern)
AND (#ZipCodeIDS IS NULL
OR p.ZipCodeID IN (select zipcodeids from #listofIDS))
AND (#NumBedroomsFrom IS NULL OR (p.NumBedrooms >= #NumBedroomsFrom
AND #NumBedroomsTo IS NOT NULL
AND p.NumBedrooms <= #NumBedroomsTo)
OR (p.NumBedrooms = #NumBedroomsFrom
AND #NumBedroomsTo IS NULL))
AND (#NumBedroomsTo IS NULL OR (p.NumBedrooms <= #NumBedroomsTo
AND (#NumBedroomsTo IS NULL OR p.NumBedrooms <= #NumBedroomsTo)))
AND (#LivingSizeFrom IS NULL OR (p.LivingSquareFeet >= #LivingSizeFrom))
AND (#LivingSizeTo IS NULL OR (p.LivingSquareFeet <= #LivingSizeTo))
AND (#LotSizeFrom IS NULL OR (p.LotSquareFeet >= #LotSizeFrom))
AND (#LotSizeTo IS NULL OR (p.LotSquareFeet <= #LotSizeTo))
AND
/* if status is null, return all. Or, return only statuses that are passed in */
(#PropertyStatuses IS NULL or
((p.PropertyStatusID=#PropertyStatuses and (p.PropertyStatusID & (32 | 128)) = 0) or
#PropertyID is not null or #PCode is not null) or
(p.PropertyStatusID = (p.PropertyStatusID & #PropertyStatuses)))
/*
-- return the property if the specific ID was given otherwise ommit Sold and Archived
AND ((p.PropertyStatusID & (32 /*sold*/ | 128 /*archived*/)) = 0
OR #PropertyID IS NOT NULL
OR #PCode IS NOT NULL))
OR (p.PropertyStatusID = (p.PropertyStatusID & #PropertyStatuses)))
*/
AND (#PropertyTypes IS NULL
OR (p.PropertyTypeID = (p.PropertyTypeID & #PropertyTypes)))
AND (#ResearchStatuses IS NULL
OR (p.ResearchStatusID = (p.ResearchStatusID & #ResearchStatuses)))
AND (#IsOnTheMLS IS NULL OR p.IsOnTheMLS = #IsOnTheMLS)
and (#strAddress is null or (p.Address1 LIKE #strAddress or p.Address2 LIKE #strAddress))
RETURN
and the same, translated by me in SQL (which works good):
/****** Script for SelectTopNRows command from SSMS ******/
SELECT TOP 1000 [PropertyID]
,[PCode]
,[Address1]
,[Address2]
,[NumBedrooms]
,[NumBathrooms]
,[LivingSquareFeet]
,[LotSquareFeet]
,[YearBuilt]
,[ZillowLink]
,[AssessorParcelNumber]
,[DateWentREO]
,[DateAppearedOnMLS]
,[IsOnTheMLS]
,[ZPropertyID]
,[LowestPrice]
,[HighestPrice]
,[AskingPrice]
,[DateTimeRecorded]
,[RecordedByPersonID]
,[AssignedToPersonID]
,[latitude]
,[longitude]
,[Zestimate]
FROM [dev_hotsheetDB].[dbo].[Properties] p
JOIN [dev_hotsheetDB].[dbo].cfgPropertyStatuses ps
ON ps.PropertyStatusID = p.PropertyStatusID
JOIN [dev_hotsheetDB].[dbo].cfgPropertyTypes pt
ON pt.PropertyTypeID = p.PropertyTypeID
JOIN [dev_hotsheetDB].[dbo].cfgResearchStatuses rs
ON rs.ResearchStatusID = p.ResearchStatusID
JOIN [dev_hotsheetDB].[dbo].ZipCodes z
ON z.ZipCodeID = p.ZipCodeID
JOIN [dev_hotsheetDB].[dbo].cfgStates s
ON s.StateID = p.StateID
LEFT JOIN [dev_hotsheetDB].[dbo].cfgCities c
ON c.CityID = p.CityID
where
(NULL IS NULL OR p.PropertyID = NULL)
AND (NULL IS NULL OR p.PCode LIKE NULL)
AND ('1' IS NULL
OR p.ZipCodeID IN (select zipcodeids from [dev_hotsheetDB].[dbo].[listofIDS]))
AND (NULL IS NULL OR (p.NumBedrooms >= NULL
AND NULL IS NOT NULL
AND p.NumBedrooms <= NULL)
OR (p.NumBedrooms = NULL
AND NULL IS NULL))
AND (NULL IS NULL OR (p.NumBedrooms <= NULL
AND (NULL IS NULL OR p.NumBedrooms <= NULL)))
AND (NULL IS NULL OR (p.LivingSquareFeet >= NULL))
AND (NULL IS NULL OR (p.LivingSquareFeet <= NULL))
AND (NULL IS NULL OR (p.LotSquareFeet >= NULL))
AND (NULL IS NULL OR (p.LotSquareFeet <= NULL))
AND
/* if status is null, return all. Or, return only statuses that are passed in */
(NULL IS NULL or
((p.PropertyStatusID=NULL and (p.PropertyStatusID & (32 | 128)) = 0) or
NULL is not null or NULL is not null) or
(p.PropertyStatusID = (p.PropertyStatusID & NULL)))
/*
-- return the property if the specific ID was given otherwise ommit Sold and Archived
AND ((p.PropertyStatusID & (32 /*sold*/ | 128 /*archived*/)) = 0
OR #PropertyID IS NOT NULL
OR #PCode IS NOT NULL))
OR (p.PropertyStatusID = (p.PropertyStatusID & #PropertyStatuses)))
*/
AND (NULL IS NULL
OR (p.PropertyTypeID = (p.PropertyTypeID & NULL)))
AND (NULL IS NULL
OR (p.ResearchStatusID = (p.ResearchStatusID & NULL)))
AND (NULL IS NULL OR p.IsOnTheMLS = NULL)
and (NULL is null or (p.Address1 LIKE NULL or p.Address2 LIKE NULL))
Please note that the issue is only related to IN statement... When #ZipCodeIDS = '1,2,3' it should return 414 results (plain sql ok) but T-SQL function returns 80..
The strange thing I've noticed is that T-SQL only takes in consideration FIRST id from #ZipCodeIDS (as you see I split these ids and put them into a temp table). So here's the issue - about this first id... (cannot confirm that this is the only issue, because there were times when for the first zipCodeId it shouldn't return anything but it still returned results)
Can you give a helping hand please?
Ps: for my plain sql query, I've used a real table with those ids, just to mimic the behavior as much as possible...
UPDATE: The splitting of the #ZipCodeIDS and insertion into the temp table works perfectly: https://data.stackexchange.com/stackoverflow/q/109406/
Solved the issue with Timbo help!!!!!
I've declared #ZipCodeIDS varchar and somehow it is made by default VARCHAR(1).
I changed it to #ZipCodeIDS varchar(50) and not it perfectly works!!!!
Sorry guys because this declaration was hidden from you!

Resources