not able to retrieve if the table column has null value - sql

I have stored procedure to find customer, its working fine. If Customer_City_Name is null in the table then I am not able to retrieve the row. SP fails . how to do this
I have to get result even if Customer_City_Name or Customer_Country_Code IS NULL
EXEC findCustomer null,'%',null,null,
SP code:
CREATE PROCEDURE findCustomer
#customerNumber NVARCHAR(100),
#customerNamePattern NVARCHAR(35),
#customerCityNamePattern NVARCHAR(35),
#customerCountryCode NVARCHAR(5)
AS
BEGIN
DECLARE #SQL NVARCHAR(4000)
SET #SQL =
'
SELECT
c.Customer_Number,
c.Customer_Name,
c.Postal_Address_Identifier,
c.Customer_Street_Or_Road_Name,
c.Customer_City_Name,
c.Customer_Territory_Code,
c.Customer_Postal_Code,
c.Customer_Country_Code,
c.Telephone_Number,
c.Mobile_Telephone_Number,
c.Fax_Number,
c.Email_Address
FROM Customer c
WHERE c.Customer_Number LIKE ' +
CASE WHEN #customerNumber IS NOT NULL
THEN '''' + #customerNumber + ''''
ELSE 'c.Customer_Number'
END + '
AND c.Customer_Name LIKE ' +
CASE WHEN #customerNamePattern IS NOT NULL
THEN '''' + #customerNamePattern + ''''
ELSE 'c.Customer_Name'
END + '
AND c.Customer_City_Name LIKE ' +
CASE WHEN #customerCityNamePattern IS NOT NULL
THEN '''' +#customerCityNamePattern + ''''
ELSE 'c.Customer_City_Name'
END + '
AND c.Customer_Country_Code LIKE ' +
CASE WHEN #customerCountryCode IS NOT NULL
THEN '''' +#customerCountryCode + ''''
ELSE 'c.Customer_Country_Code'
END
EXEC sp_executesql #SQL

#user2218371 you should reconsider alternatives instead of dynamic SQL. anyway, this is an alternative code.
CREATE PROCEDURE findCustomer
#customerNumber NVARCHAR(100),
#customerNamePattern NVARCHAR(35),
#customerCityNamePattern NVARCHAR(35),
#customerCountryCode NVARCHAR(5)
AS
BEGIN
DECLARE #SQL NVARCHAR(4000)
SET #SQL =
'
SELECT
c.Customer_Number,
c.Customer_Name,
c.Postal_Address_Identifier,
c.Customer_Street_Or_Road_Name,
c.Customer_City_Name,
c.Customer_Territory_Code,
c.Customer_Postal_Code,
c.Customer_Country_Code,
c.Telephone_Number,
c.Mobile_Telephone_Number,
c.Fax_Number,
c.Email_Address
FROM Customer c
WHERE ' +
CASE WHEN #customerNumber IS NOT NULL
THEN ' c.Customer_Number LIKE ''' + #customerNumber + '''' +
CASE WHEN #customerNamePattern IS NOT NULL THEN ' AND ' ELSE '' END
ELSE ''
END +
CASE WHEN #customerNamePattern IS NOT NULL
THEN ' c.Customer_Name LIKE ''' + #customerNamePattern + '''' +
CASE WHEN #customerCityNamePattern IS NOT NULL THEN ' AND ' ELSE '' END
ELSE ''
END +
CASE WHEN #customerCityNamePattern IS NOT NULL
THEN ' c.Customer_City_Name LIKE ''' + #customerCityNamePattern + '''' +
CASE WHEN +#customerCountryCode IS NOT NULL THEN ' AND ' ELSE '' END
ELSE ''
END +
CASE WHEN #customerCountryCode IS NOT NULL
THEN ' c.Customer_Country_Code LIKE ''' + #customerCountryCode + ''''
ELSE ''
END
EXEC sp_executesql #SQL

When one of the fields is NULL, your WHERE clause looks like this:
WHERE c.Customer_Number LIKE c.Customer_Number
This is clearly intentional, since it is part of the CASE statements.
However, LIKE doesn't return true for a pair of NULL values. (NULL is not LIKE NULL.) This is pretty typical behavior for NULL. = does the same thing.
See this very simple SQL Fiddle for a demonstration: http://sqlfiddle.com/#!3/82a23/3/0.
Assuming I'm reading this correctly, you want to simply ignore the column's value when the procedure argument is NULL. In that case, you will need to adjust your query to leave out the clause entirely or put some always true expression in its place when the argument is NULL.
If you insist on sticking with your dynamic SQL building function (which you should not), try this for your CASE statements:
WHERE ' +
CASE WHEN #customerNumber IS NOT NULL
THEN 'c.Customer_Number LIKE ''' + #customerNumber + ''''
ELSE '0=0'
END + '

Null values cant be compared with any other value, that means you don't get a True or a False.
To work around this issue I use the ISNULL built in function that checks if the value is null, and if it is returns your default value.
You should apply this function to each column where a null value is an option.
http://msdn.microsoft.com/en-us/library/ms184325.aspx

brother, so your query mainly is to perform select function to search for existing customer info
try to modify your where condition as sample below
Select ....
From .....
WHERE (#Customer_Number is null or c.Customer_Number like #Customer_Number + '%')
AND (#customerNamePattern is null or c.Customer_Name like #customerNamePattern + '%' )
AND (#customerCityNamePatternis null or c.Customer_City_Name like #customerCityNamePattern+ '%' )
AND (#customerCountryCode is null or c.c.Customer_Country_Code like #customerCountryCode + '%' )

I have fixed this issue by doing this
AND ISnull(c.Customer_City_Name,'''') LIKE ' +
CASE WHEN #customerCityNamePattern IS NOT NULL
THEN '''' +#customerCityNamePattern + ''''
ELSE 'isnull (c.Customer_City_Name,'''')'
END + '
AND Isnull(c.Customer_Country_Code,'''') LIKE ' +
CASE WHEN #customerCountryCode IS NOT NULL
THEN '''' +#customerCountryCode + ''''
ELSE 'isnull(c.Customer_Country_Code , '''')'
END
1.Thanks to asafrob i have accepted your approach.
2. Thanks to devio In 'LIKE' operator needs to select 'NULL'(DB) values I got idea from
3.Thanks to jpmc26 -- > I like your answer .
Finally thanks to every one answered to my question

Related

Where Clause from Another table

So the goal is to make a SQL query for table A but the where clause is stored in table B.
here is example
table B:
BatchNumber | DataItem | Operator | TValue
12345 | Branch | = | 2700
12345 | StockType| = |S
12345 | PRCode | <> |AD
from this table I need to make below where statement
select *
from testdata.TableA
where Branch = 2700 and StockType = 'S' and PRCode <> 'AD'
here are the different methods I tried using to form a sql
declare #whereClause varchar(400)
declare #schema varchar(10) = 'testdata'
declare #Batch varchar(15) = 12345
select #whereClause = N' COALESCE(#whereClause + ' ' ,'') + trim(DataItem) + ' ' + trim(Operator) + ' ' +
case
when trim(TValue) LIKE '[A-Za-z]%' then '''' + trim(TValue) + '''' + ' AND'
when trim(TValue) = ' ' then '''' + '''' + ' AND'
else trim(TValue) + ' AND'
end
from' + #schema + '.TableB where BatchNumber =' + #Batch
--remove AND from the end of statement
SET #whereClause = SUBSTRING(#whereClause,0, LEN(#whereClause) - 3)
PRINT #whereClause
However this is giving me syntax error with single codes in the case statement.
Msg 102, Level 15, State 1, Line 4
Incorrect syntax near ' ,') + trim(DataItem) + '.
I need case statement to add single quote around string operators.
I also tried different method with FOR XML PATH(''), but with this single quotes are eliminated and "<>" signs are changed to "gtlt"
really appreciate any help.
It seems like some of your single-quotations may have to be quoted or you could use variables. For example: #whereClause = N' COALESCE(#whereClause + ' ' ,'')... may require #whereClause = N' COALESCE(#whereClause + '' '' ,'''')... or something on those lines. You could store there result of COALESCE(#whereClause + ' ' ,'') in a variable and then concat it with other variables in a similar way.
Alternatively, you could write a query in SQL Server like this:
select 'select * '
union all select 'from testdata.TableA '
union all select 'where 1 = 1 '
union all
select concat(
' and ',
dataitem, ' ', operator, ' ',
case
when tvalue like '%[0-9]%' then tvalue
else concat('''', tvalue, '''')
end
)
from test /* or tableB */
where batchnumber = 12345; /*optional where clause*/
You'll get the output like this:
select *
from testdata.TableA
where 1 = 1
and Branch = 2700
and StockType = 'S'
and PRCode <> 'AD'
Example:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=12c3110a0d82e754bfc16f686779cddd

MSSQL searching unicode characthers using LIKE operator

I have a stored procedure where I pass a parameter that is unicode and looks like following:
מוכר שמן קוקוס בכחל מיני ואריציות
Now the problem here is that when I enter something in my form to search for this value in m table like fllowing:
IF LEN(#SearchValue) > 0
BEGIN
SET #WhereQuery = #WhereQuery +
'(Type=' + CAST(#type AS NVARCHAR(10)) + ' and UserId=' + CAST(#userid AS NVARCHAR(10)) + ') and'
+ '(convert(nvarchar(max),SentWord) like ''%' + #SearchValue + '%'' or '
+ 'convert(nvarchar(max),Comment) like ''%' + #SearchValue + '%'')'
END
Where #SearchValue is defined as nvarchar(200) in SQL server and table columns that hold the specific value are:
SentWord and Comment and both are unicode defined as nvarchar(600).
What am I doing wrong here? Why cant MSSQL search by hebrew characthers ? Can someone help me out?
As #Jeroen stated , possible fix would be to add N after LIKE operator like following:
IF LEN(#SearchValue) > 0
BEGIN
SET #WhereQuery = #WhereQuery +
'(Type=' + CAST(#type AS NVARCHAR(10)) + ' and UserId=' + CAST(#userid AS NVARCHAR(10)) + ') and'
+ '(convert(nvarchar(max),SentWord) like N''%' + #SearchValue + '%'' or '
+ 'convert(nvarchar(max),Comment) like N''%' + #SearchValue + '%'')'
END
But it still doesn't works...
Don't concatenate your strings like that!!! It's an injection nightmare!
Next, your declaring your literal unicode string as a varchar, not an nvarchar. if you try SELECT 'מוכר שמן קוקוס בכחל מיני ואריציות'; notice the return value is '???? ??? ????? ???? ???? ????????'. You need to prefix it with N, thus: SELECT N'מוכר שמן קוקוס בכחל מיני ואריציות';.
Now, the important is parametrising that SQL... Unfortunately I don't have enough of the SQL to actually do this in full for you, so here's a different example instead:
DECLARE #SQL nvarchar(MAX);
DECLARE #string nvarchar(20) = N'Test';
SET #SQL = 'SELECT * FROM MyTable WHERE MyColumn = #dString;'; --Notice the variable in the dynamic SQL
PRINT #SQL;
EXEC sp_executesql #SQL, N'dString nvarchar(20)',#dString = #string; --Notice the variable declaration and assignment.

Strange behavior with ISNULL() in MSSQL

I have a select statement that is combining multiple segments of a persons name. This isn't anything new.
SELECT FirstName + ' ' + LastName AS FullName FROM MyTable
I then tried to add the middle initial to this and I came up with the following
SELECT FirstName + ' ' + ISNULL(MiddingInitial + ' ', '') + LastName AS FullName FROM MyTable
This appears to work, but during my testing of ISNULL(), I came across an odd behavior. I'm aware that NULL + 'any string' resolves to NULL. However this was just plain odd...
Here's my code, and what I get out as a result...
print '''' + isnull(null + 'Any String','Results in null') + ''''
print '''' + isnull(null + 'Any','Results in null') + ''''
print '''' + isnull(null + 'A','Results in null') + ''''
print '''' + isnull(null + '','Results in null') + ''''
/*
'Results in '
'Resu'
'Re'
'Re'
*/
Any idea of why this behavior occurs? Does it do the same for you?
It comes down to the datatypes you're working with and the behavior of the ISNULL function. Let's look at one example:
null + 'Any String'
The above fits perfectly into a varchar(11) datatype. The NULL (which is really just the result of char(0) and has length 1) and a regular 10-character string concatenated together makes for 11 characters total. The replacement string -- the second parameter to your ISNULL function -- is going to be forced to fit into a varchar(11), so it is truncated to 11 characters.
The pattern repeats for the remaining items, with a special case for the empty string.
If you don't want this to happen, use COALESCE, which instead of taking the datatype of the first item in the list, it uses data type precedence. A varchar(15) takes precedence over a varchar(11), so you will get the full replacement string:
print '''' + coalesce(null + 'Any String','Results in null') + ''''
print '''' + coalesce(null + 'Any','Results in null') + ''''
print '''' + coalesce(null + 'A','Results in null') + ''''
print '''' + coalesce(null + '','Results in null') + ''''
/*
'Results in null'
'Results in null'
'Results in null'
'Results in null'
*/

Return a percentage of NULL values for a specific record

The following query returns the values of the table for each field in terms of null percentage . What I want is to get the sum of those percentages for a specific ProductID. Also, I would like to get a percentage (in an extra column) of the fields do not have value i.e. ="". Any ideas?
use AdventureWorks
DECLARE #TotalCount decimal(10,2), #SQL NVARCHAR(MAX)
SELECT #TotalCount = COUNT(*) FROM [AdventureWorks].[Production].[Product]
SELECT #SQL =
COALESCE(#SQL + ', ','SELECT ') +
'cast(sum (case when ' + QUOTENAME(column_Name) +
' IS NULL then 1 else 0 end)/#TotalCount*100.00 as decimal(10,2)) as [' +
column_Name + ' NULL %]
'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Product' and TABLE_SCHEMA = 'Production'
SET #SQL = 'set #TotalCount = NULLIF(#TotalCount,0)
' + #SQL + '
FROM [AdventureWorks].Production.Product'
print #SQL
EXECUTE SP_EXECUTESQL #SQL, N'#TotalCount decimal(10,2)', #TotalCount
You can use the following:
use AdventureWorks
DECLARE #colCount int;
DECLARE #nullCheck nvarchar(max) = N'';
DECLARE #emptyCheck nvarchar(max) = N'';
DECLARE #SQL NVARCHAR(MAX);
DECLARE #KeyToCheck int = 123; -- adapt as necessary
SELECT
#nullCheck += '
+ ' + 'count(' + QUOTENAME(column_Name) + ')'
,#emptyCheck += '
+ ' +
CASE
WHEN DATA_TYPE IN('bigint', 'int', 'smallint', 'tinyint', 'bit', 'money', 'smallmoney', 'numeric', 'decimal', 'float', 'real') THEN
-- check numeric data for zero
'sum(case when coalesce(' + QUOTENAME(column_Name) + ', 0) = 0 then 1 else 0 end)'
WHEN DATA_TYPE like '%char' or DATA_TYPE like '%text' THEN
--check character data types for empty string
'sum(case when coalesce(' + QUOTENAME(column_Name) + ', '''') = '''' then 1 else 0 end)'
ELSE -- otherwise, only check for null
'sum(case when ' + QUOTENAME(column_Name) + ' IS NULL then 1 else 0 end)'
END
,#colCount =
count(*) over()
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Product' and TABLE_SCHEMA = 'Production'
;
SET #SQL = 'SELECT case when count(*) > 0 then 100.00 - (' + #nullCheck + '
) * 100.00 / ' + cast(#colCount as nvarchar(max)) + '.00 / count(*) end as null_percent
, case when count(*) > 0 then (' + #emptyCheck + '
) * 100.00 / ' + cast(#colCount as nvarchar(max)) + '.00 / count(*) end as empty_percent
FROM Production.Product
WHERE ProductID = ' + cast(#KeyToCheck as nvarchar(max))
;
print #SQL;
EXECUTE (#SQL)
I simplified one of your expressions: Instead of sum (case when <column> IS NULL then 1 else 0 end), you can just use count(<column>). When using count with an expression instead of *, it counts the rows where this expression is non-null. As this is the opposite from what you need, I added the 100.00 - as the start of the SELECT.
For the "empty check", this would make the logic more complex to understand, hence I left the original logic there and extended it. There, I implemented an check for emptiness for numeric and character/text data types. You can easily extend that for date, binary data etc. with whichever logic you use to determine if a column is empty.
I also found it more simple to leave first + in the two variables #nullCheck and #emptyCheck, as it is valid SQL to start an expression wit this.
I also extended the statement so that if there would potentially be more than one record with ProductId = 123, it shows the average across all records, i. e. the total sum divided by the count of rows. And the outermost case expressions just avoid an division by zero error if count(*) would be zero, i. e. no record with ProductId = 123 found. In that case the return value is null.
You could use AVG function:
SELECT AVG(CASE WHEN value IS NULL THEN 100 ELSE 0 END) AS Percents
FROM Table
UPDATE:
Here is your script:
DECLARE #SQL NVARCHAR(MAX), #TABLE_NAME NVARCHAR(MAX), #TABLE_SCHEMA NVARCHAR(MAX), #PK NVARCHAR(MAX)
SET #TABLE_NAME = 'tblBigTable'
SET #TABLE_SCHEMA = 'dbo'
SET #PK = '8'
SELECT
#SQL = COALESCE(#SQL + ', ', 'SELECT ') +'AVG(CASE WHEN ' + COLUMN_NAME + ' IS NULL THEN 100 ELSE 0 END) AS [' + COLUMN_NAME +' NULL %]'
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = #TABLE_SCHEMA AND
TABLE_NAME = #TABLE_NAME
SET #SQL = #SQL + ' FROM ' + #TABLE_NAME + ' WHERE pkId = ''' + #PK + ''''
print #SQL
EXECUTE SP_EXECUTESQL #SQL

Converting Dirty SQL Code to Something Clean and Efficient

I have to modify some SQL code that does not seem to be working as it is supposed to.
The SQL code looks awful to me, but it works for the most part.
Say we had multiple vendors with similar names: Microsoft, Microsoft Corp, and Microsoft, Inc, etc.
All the query returns is Microsoft, even though the existing code includes the line PRI_VENDOR_NAME like '%' #PRI_VENDOR_NAME '%' (or, at least it looks like it does).
I can't seem to check to see if the code is working because it is one big, nasty looking piece of code that is appending data to a long string to execute.
CURRENT PROCEDURE: (Get ready to scream)
ALTER PROCEDURE [dbo].[GetSignalMasterByFilter]
(
#planner varchar(50),
#reorder int,
#release int,
#CMTTED varchar(50),
#partid varchar(50),
#global_short_dt int,
#PRI_VENDOR_NAME varchar(50)
)
AS
BEGIN
DECLARE #Filter nvarchar(4000)
set #Filter = ' '
if #planner <> ''
begin
set #Filter = ' and planner in(' + #planner + ')'
end
if #reorder = 1
begin
set #Filter = rtrim(#Filter) + ' and (REORDER_50 = ' + char(39) + 'Y' + char(39) + ' ) '
end
if #reorder = 2
begin
set #Filter = rtrim(#Filter) + ' and (REORDER_30 = ' + char(39) + 'Y' + char(39) + ' ) '
end
if #reorder = 3
begin
set #Filter = rtrim(#Filter) + ' and (REORDER_POINT = ' + char(39) + 'Y' + char(39) + ' ) '
end
--if #noaction = 1
--begin
--set #Filter = rtrim(#Filter) + ' and reorder in (' + char(39) + 'Excess' + char(39) + ',' + char(39) + 'Watch' + char(39) + ')'
--end
if #release = 1
begin
set #Filter = rtrim(#Filter) + ' and (RELEASE_50 = ' + char(39) + 'Y' + char(39) + ' ) '
end
if #release = 2
begin
set #Filter = rtrim(#Filter) + ' and (RELEASE_30 = ' + char(39) + 'Y' + char(39) + ' ) '
end
if #release = 3
begin
set #Filter = rtrim(#Filter) + ' and (RELEASE_POINT = ' + char(39) + 'Y' + char(39) + ' ) '
end
if #CMTTED <> 'View ALL'
begin
set #Filter = rtrim(#Filter) + ' and CMTTED > ' + char(39) + '0' + char(39) + ' and isnumeric(CMTTED) = 1 '
end
if #global_short_dt = 1
begin
set #Filter = rtrim(#Filter) + ' and (global_short_dt is not null or cast(CMTTED as int) > cast(ON_HAND as int)) '
end
if #global_short_dt = 2
begin
set #Filter = rtrim(#Filter) + ' and (global_short_dt is not null or cast(CMTTED as int) > cast(ON_HAND as int)) AND ((cast(QTY_IN_STATUS as float) + cast(ON_ORDER as float) + cast(ON_HAND as float)) < cast(CMTTED as int)) '
end
if #partid <> ''
begin
set #Filter = rtrim(#Filter) + ' and partid like(' + char(39) + #partid + '%' + char(39) + ')'
end
if #PRI_VENDOR_NAME <> ''
begin
set #Filter = rtrim(#Filter) + ' and PRI_VENDOR_NAME like(' + char(39) + #PRI_VENDOR_NAME + '%' + char(39) + ')'
end
DECLARE #sql nvarchar(4000)
SET #sql = '
SELECT DISTINCT PRIMARY_VENDOR,case when PRI_VENDOR_NAME is null then PRIMARY_VENDOR else PRIMARY_VENDOR +' + char(39) + ' - ' + char(39) + '+ PRI_VENDOR_NAME end as PRI_VENDOR_NAME
FROM SignalReportView WHERE PRIMARY_VENDOR is not null ' + rtrim(#filter) + ' order by PRI_VENDOR_NAME'
--print #sql
EXEC sp_executesql #sql
end
What I want to do is replace that nasty looking string variable with something that I've started below, but SQL is not my strength so it isn't quite returning any data just yet:
MY PROCEDURE VERSION: Does not return the data, but appears to be cleaner and easier to maintain in the future.
ALTER PROCEDURE GetSignalMasterByFilter2(
#planner varchar(50),
#reorder int,
#release int,
#CMTTED varchar(50),
#partid varchar(50),
#global_short_dt int,
#PRI_VENDOR_NAME varchar(50)
) as begin
SELECT DISTINCT
PRIMARY_VENDOR,
case when PRI_VENDOR_NAME is null then PRIMARY_VENDOR else PRIMARY_VENDOR +' - '+ PRI_VENDOR_NAME end as PRI_VENDOR_NAME
FROM
SignalReportView
WHERE
(PRIMARY_VENDOR is not null)
and (
ISNULL(#planner,0)=0 or
planner in (#planner))
and (
(#reorder=1 and REORDER_50='Y') or
(#reorder=2 and REORDER_30='Y') or
(#reorder=3 and REORDER_POINT='Y') or
(1=1)
)
and (
(#release=1 and RELEASE_50='Y') or
(#release=2 and RELEASE_30='Y') or
(#release=3 and RELEASE_POINT='Y') or
(1=1)
)
and (
(#CMTTED='View ALL') or
(0<CMTTED and ISNUMERIC(CMTTED)=1)
)
and (
(
(#global_short_dt=1) and
(
(GLOBAL_SHORT_DT is not null) or
(CAST(ON_HAND as int) < CAST(CMTTED as int))
)
) or
(1=1)
)
and (
(
(#global_short_dt=2) and
(
(GLOBAL_SHORT_DT is not null) or
(
(CAST(ON_HAND as int) < CAST(CMTTED as int)) and
((CAST(QTY_IN_STATUS as float) + CAST(ON_ORDER as float) + CAST(ON_HAND as float)) < CAST(CMTTED as int))
)
)
) or
(1=1)
)
and (
ISNULL(#partid,0)=0 or
(PARTID like '%'+#partid+'%')
)
and (
ISNULL(#PRI_VENDOR_NAME,0)=0 or
(PRI_VENDOR_NAME like '%'+#PRI_VENDOR_NAME+'%')
)
ORDER BY PRI_VENDOR_NAME
end
So, my question is:
Is it a good idea to rewrite the original script with a version that should be easier for other developers to maintain in the future?
If NO, can someone spot why the existing SQL is not returning all vendors?
If YES, can someone guide me with the design of my version? It is NOT currently working - probably because I have some logic wrong. Also, the (1=1) clauses do not set well with me, but I don't know a way around them. Since my procedure does not return any data, I can not use it at this point.
I apologize for not posting the table structures, but they are all rather large, and the Stored Procedure above queries an even nastier looking view (that I can't even follow).
I have been in a similar situation many times. With me.... it's usually my own code that I am trying to clean up.
When doing things like this, please do not ONLY consider code readability. You must also consider the impact on the server. Often times, there are various ways to write a query that produces identical results. In those situations, you should pick the version that executes the fastest. If this means you are using the "uglier" version, so be it.
Clearly, you looked at the original code and thought, "Huh?". This is a good indication that there should be code comments.
I haven't spent much time looking at the code, but it appears as though there are various optional parameters to the procedure (option in that empty string indicates that the code should ignore that parameter). It is possible to write code that accommodates this situation without using dynamic sql, but that code almost always executes slower. Read here for an explanation: Do you use Column=#Param OR #Param IS NULL in your WHERE clause? Don't, it doesn't perform
I think G Mastros gave you the right answer for the question. I only want to clarify as I see it myself.
First of all if your procedure will execute faster, nothing else matters with large data.
Secondly, your version is much harder to follow for me than the first one.
And by adding comments to each param and set it will be totally easier to read.
So my answer is NO and of course it's not returning all vendors because of conditions in #filter. Just print it before execution to see conditions that maked up earlier by given parameters.
Try something like this:
ALTER PROCEDURE GetSignalMasterByFilter2(
#planner varchar(50),
#reorder int,
#release int,
#CMTTED varchar(50),
#partid varchar(50),
#global_short_dt int,
#PRI_VENDOR_NAME varchar(50)
) as
begin
SELECT DISTINCT
PRIMARY_VENDOR,
case when PRI_VENDOR_NAME is null then PRIMARY_VENDOR else PRIMARY_VENDOR +' - '+ PRI_VENDOR_NAME end as PRI_VENDOR_NAME
FROM
SignalReportView
WHERE
PRIMARY_VENDOR is not null
and
(
#Planner IS NULL
OR #planner = ''
OR planner in (#planner))
and
( #reorder NOT IN (1,2,3) OR
(#reorder=1 and REORDER_50='Y') or
(#reorder=2 and REORDER_30='Y') or
(#reorder=3 and REORDER_POINT='Y')
)
and
(
#release NOT IN (1,2,3) OR
(#release=1 and RELEASE_50='Y') or
(#release=2 and RELEASE_30='Y') or
(#release=3 and RELEASE_POINT='Y')
)
and
(
#CMTTED='View ALL' or
0<CMTTED and ISNUMERIC(CMTTED)=1
)
and
(
#global_short_dt NOT IN (1,2) OR
(global_short_dt is not NULL AND #global_short_dt=1 AND CAST(ON_HAND as int) < CAST(CMTTED as int)) OR
(global_short_dt is not NULL AND #global_short_dt=2 AND CAST(ON_HAND as int) < CAST(CMTTED as int)
and (CAST(QTY_IN_STATUS as float) + CAST(ON_ORDER as float) + CAST(ON_HAND as float)) < CAST(CMTTED as int))
)
and
(
#partid IS NULL OR
#partid = '' OR
PARTID like '%'+#partid+'%'
)
and
(
#PRI_VENDOR_NAME IS NULL OR
#PRI_VENDOR_NAME = '' OR
PRI_VENDOR_NAME like '%'+#PRI_VENDOR_NAME+'%'
)
ORDER BY PRI_VENDOR_NAME
end
I think I have fixed all your logic mistakes, but as I don't have any tables it is not tested.
As for the performance, you'd have to check both versions and see. There is no guarantee either way.