Help deciphering Stored Procedure - sql

I can't for the life of me figure out how this stored procedure works or what it is doing exactly, I know it works as is but I'm trying to limit some database calls which requires modifying this stored procedure.
CREATE PROCEDURE scriptassist.getQueue
#Status smallint = -1,
#GroupID uniqueidentifier = null,
#MACAddress varchar(200) = ''
AS
SET NOCOUNT ON
Print #GroupID
SELECT *
FROM [Queue]
WHERE
case #Status
When -1 Then
Case When ISNULL(Status,0) <> 1 Then 1 Else 0 End
Else
Case When ISNULL(Status,0) = #Status Then 1 Else 0 End
End =1
And
case When #GroupID IS NULL Then 1
Else
Case When GroupID = #GroupID Then 1 Else 0 End
End =1
And
case #MACAddress
When ''
Then 1
Else
Case When MACAddress = #MACAddress Then 1 Else 0 End
End =1
Order By DateEntered DESC
I know that somehow it is dynamically defining the Where Clause but I'm not sure what is getting done. Also if anyone knows of a tool that would let me see what is actually happening, thanks!

You're right in noticing that it's dynamically filtering the WHERE clause. Take for example
case #MACAddress
When ''
Then 1
Else
Case When MACAddress = #MACAddress Then 1 Else 0 End
End =1
If the MACAddress is the empty string then it is not used to filter the results. (The Case statement returs 1, which is then compared with 1 at the end, resulting in TRUE, so the row is included.)
If the #MACAddress parameter is not the empty string, then it's compared with the MACAddress column in the table. If there is a match 1, is returned, which is equal to 1, and so the row is included. If there is no match, 0 is returned, which does not equal 1 and the row is excluded.

Selects values from Queue based on three criteria that could be passed. If the passed variable #Status=-1, or #GroupID is null, or #MACAddress ='', they are not used in the Where criteria. If they are present, then they are used in the Where criteria.
When each case statement returns 1, the corresponding record in the Queue table is returned.

Related

SQL Filter SELECT statement

I need to filter my select statement to only grab a value is a bit value is true. For example
DECLARE
#Value AS NVARCHAR(20) = 'Some Value'
#BIT AS BIT = 1,
#Stuff AS NVARCHAR(20) = 'Stuff'
SELECT
#Stuff,
IF #BIT = 1 BEGIN #Value END ELSE BEGIN '' END
Something like this basically. I only want to select the value if its true. I have multiple checkboxes and the data should only pull that data back if the user selects one of those check boxes so I'm using bit's to track if its checked or not. Thanks in advance
Use CASE not IF:
SELECT
#Stuff,
CASE WHEN #BIT = 1 THEN #Value ELSE '' END
or
CASE #BIT WHEN 1 THEN #Value ELSE '' END
It's a little unclear what you are trying to do, so I will give you several approaches:
If you are limiting your select statement, you can do:
SELECT ...
FROM ...
WHERE myBitField = 1
or, if your bit field is a variable that's being passed in, you can do:
SELECT ...
FROM ...
WHERE myBitField = #BIT
If you don't want to limit your select results, you can use a case statement:
SELECT CASE WHEN #BIT = 1 THEN #Value ELSE '' END as BitResult
FROM ...

Passing parameter to divide field value to stored procedure makes it slow

Recently I made a change to my stored procedure to pass a parameter value to divide the value of one of the fields... and stored procedure became very slow. It was taking 1 minute to run 600 recs and now its taking 8-9 minutes to run same results. Could you please help improve this little change?
I only added the following line in the select list
(nullif(x.tardies, 0) / #addtardies) addtardies
Here's the complete code:
ALTER PROCEDURE [dbo].[z_testCalc]
(
#calendarID int,
#grade varchar(3),
#AbsType varchar(1),
#Tardies varchar(1),
#startDate smallDateTime,
#endDate smallDateTime,
#TeamActivity varchar(50),
#Percent VARCHAR(10),
#AddTardies int
)
AS
BEGIN
SET NOCOUNT ON;
select distinct
x.test1,
x.test2,
x.AbsType,
x.UnexAbs,
x.ExAbs,
x.Tardies,
mp.meetings,
round((1 - cast(x.UnexAbs as decimal(6,3))/cast(mp.meetings as decimal(6,3))) * 100,1) percentPres,
**(nullif(x.tardies, 0) / #addtardies) addtardies,**
x.endDate
from
(SELECT DISTINCT
sch.test1,
p.test1,
case when #AbsType = 'T' then 'Unexc, Exc' when #AbsType = 'U' then 'Unexc' else 'Exc' end 'AbsType',
sum(case when COALESCE(x.status, a.status) = 'A' and CASE WHEN a.excuseID IS NOT NULL THEN x.excuse ELSE a.excuse END = 'U' then 1 else 0 end) 'UnexAbs',
sum(case when COALESCE(x.status, a.status) = 'A' and CASE WHEN a.excuseID IS NOT NULL THEN x.excuse ELSE a.excuse END = 'E' then 1 else 0 end) 'ExAbs',
sum(case when COALESCE(x.status, a.status) = 'T' then 1 else 0 end) 'Tardies',
ros.endDate
FROM
test1 a WITH (NOLOCK)
Thank you in advance.
This doesn't look to me like a likely scenario for huge parameter sniffing issues. Still, when introducing a parameter results in bizarre slowdowns like you describe, I always like to rule it out.
Try adding a line that assigns your parameter to a local variable, and then use the local variable, not the parameter, in your query.
so put this at the top, before the query...
DECLARE #AddTardies_lcl int
SET #AddTardies_lcl = #AddTardies
and then use #AddTardies_lcl in your new logic.
(nullif(x.tardies, 0) / #AddTardies_lcl) addtardies
hope it helps!

how to get "AND" of all the values of a boolean column in a single sql

how to get "AND" of all the values of a boolean column in a single sql query.
for above the o/p should be false,
if all were true then o/p: true,
if all/atlease one value false , then o/p: false.
Try this
IF EXISTS (SELECT ActiveStatus From TableName where ActiveStatus = 0)
SELECT 'False'
ELSE
SELECT 'True'
AS OutputColumn
You can indirectly use MIN for AND, and MAX for OR.if you take into account that a BIT colum is either zero or one:
MIN: only if all the values are 1 (true) the result will be 1 (true), it works like AND
MAX: if there is at least a 1 (true) the result will be 1 (true), it works like OR
If you try to use MIN or MAX directly on a BIT column, it will fail, so you need to cast it to an integer type, and back to bit, like this:
SELECT CAST(MIN(CAST(BitColumn AS TINYINT)) AS BIT) FROM Table -- for AND
SELECT CAST(MAX(CAST(Bitcolumn AS TINYINT)) AS BIT) FROM Table -- for OR
It's easy to include this in a more complex query, for example one with GROUP BY
declare #status varchar(10)
if exists(select null from [Status] where ActiveStatus = 0)
set #status = 'false'
else
set #status = 'true'
select #status as [Status]

CASE statement giving wrong results inside my stored procedure

I have a case inside my stored procedure which I use before executing the data.
DECLARE #Setup nvarchar(50)
SELECT
#ZipCode = CASE
WHEN REPLACE(#ZipCode, '0', '') = ''
THEN NULL ELSE #ZipCode
END,
#ZipCodeEND = CASE
WHEN REPLACE(#ZipCodeEND, '0', '') = ''
THEN NULL ELSE #ZipCodeEND
END,
SELECT
#Setup = CASE WHEN (LEN(ISNULL(#ZipCode, ''))) > 0 THEN '1' ELSE '0' END +
CASE WHEN (LEN(ISNULL(#ZipCodeEND,''))) > 0 THEN '1' ELSE '0' END
IF ISNULL(#ID, 0) = 0
BEGIN
INSERT INTO dbo.MapToStaticValuesTable(ZipCode, ZipCodeEND, Setup)
VALUES(#ZipCode, #ZipCodeEND, #Setup)
END
The problem here is even if zipcode and zipcodeEnd are empty and set to null after being saved into the table I keep getting the value "11" instead of getting "00".
Now if I do the same example with nvarchar values it would work, but since ZipCode and ZipCodeEnd are set to int it's acting weird.
It is acting weird because you are using string functions on integers. Not sure what you are trying to achieve with your code but I'm sure it can be done just by checking the values as integers.
I guess this could be what you are looking for.
select case when nullif(#ZipCode, 0) is null then '0' else '1' end +
case when nullif(#ZipCodeEND, 0) is null then '0' else '1' end
One example of weird
select isNull(#ZipCode, '')
return 0 if #ZipCode is null.

Sql Server conditional Contains for free text search handling of Null parameter

I have been struggling for quite some time to get this query going.
In short my query searches by fileno and/or searchfield
DECLARE #pSearchFor AS NVARCHAR(100);
-- I am here testing with null value, ' ' , or seperate words
SET #pSearchFor = null -- '"marsa" and "mosta"';
IF ISNULL(#pSearchFor,'') = '' SET #pSearchFor = '""' ;
declare #fileNo nvarchar(50) = 'e/e'
select top 1000 r.FileId, r.FileNo, fs.SearchField, #pSearchFor
from regfile as r
left outer join FileSearchFields as fs on r.FileId = fs.FileID
where r.FileNo like
CASE
WHEN Len(#fileno) > 1 THEN '%'+#fileNo+'%'
ELSE r.FileNo
END
AND
1 =
CASE WHEN ISNULL(#pSearchFor, '') = '' THEN 1 ELSE 0 END
or CONTAINS(fs.SearchField, #pSearchFor)
I am getting nothing returned if #pSearchFor is null otherwise works great.
I need to return all instances if a null
One possible solution might be to call 2 seperate sps or use if /else but probably exists a better method.
I really do appreciate your help!
First you set #pSearchFor to "":
IF ISNULL(#pSearchFor,'') = '' SET #pSearchFor = '""' ;
That means this will never return 1:
CASE WHEN ISNULL(#pSearchFor, '') = '' THEN 1 ELSE 0 END
You need to either use a different variable, or use the same type of CASE expression in the select list, instead of changing the value from NULL to "".
SELECT TOP 1000 r.FileId, r.FileNo, fs.SearchField,
CASE WHEN COALESCE(#pSearchFor, '') = '' THEN '""' ELSE #pSearchFor END
Also you use SELECT TOP but no ORDER BY ... if you want a subset, don't you care which subset you get?
I have solved the problem. Maybe this may be of some help to others!
This is a snippet of my stored procedure.
#fileNo nvarchar(50) = null ,
#fields nvarchar(100) = '""',`enter code here`
#datefrom date = null,
#dateto date = null,
...
AS`enter code here`
BEGIN
if (#fields = null or LEN(#fields) < 1 ) set #fields = '""'
select top 1000 r.*,
(CASE
WHEN fs.SearchField IS NULL THEN CONVERT(NVarChar(1),'')
ELSE CONVERT(NVarChar(MAX),fs.SearchField)
END) AS [Search]
from regfile as r
left outer join FileSearchFields as fs on r.FileId = fs.FileID
where r.FileNo like
CASE
WHEN Len(#fileno) > 1 THEN '%'+#fileNo+'%'
ELSE r.FileNo
END
and
r.Date between
CASE
WHEN #datefrom != '' THEN #datefrom
ELSE '1900-1-1'
END
and
CASE
WHEN #dateto != '' THEN #dateto
ELSE '9999-1-1'
END
and
((LEN(#fields) > 2 and contains(fs.SearchField,#fields))or (LEN(#fields) <= 2))
--NB: <= 2 as we have added the "" characters in #fields!
end