I am running a SQL query that may return an empty rowset. I want to handle that with using a CASE statement.
This what I have tried but is not working
Case
When ##ROWCOUNT > 0 Then LTRIM(RTRIM(t.FirstName)) Else 'UNKNOWN'
End
The case statement does not return any value
If I use print ##RowCount rather then Select I get a 0 value.
How can I solve this?
Okay the query is rather large so I'll try to explain what it does. I am using this in a function that returns data from our HR database. I need Employee information such as name and work assignments. There are cases where I need to process the data where the employee is unknown. In those cases I pass an employeeId number of zero. That results in an empty return when I run the query.
What I would like to do is have the function return the Name data as UNKNOWN.
Hope this helps clear up the request a little
I have trimmed up the query so I can show all of the relevant parts below:
DECLARE #EID int = 0
DECLARE #AssignmentType varchar(max) = 'FirstName'
DECLARE #ReturnValue varchar(max)
DECLARE #EIDTemp TABLE(EID varchar(6), Section varchar(max), Division
varchar(max), Bureau varchar(max), FirstName varchar(max), MiddleName
varchar(max), LastName varchar(max));
Insert Into #EIDTemp
SELECT L1.Employee, P1.NAME As Section,
CASE
WHEN L1.DEPARTMENT IN (7010) THEN 'Legal Services Division'
WHEN L1.DEPARTMENT IN (7030,7040) THEN 'Fiscal Management Division'
Else 'Other'
END AS Division,
CASE
WHEN L1.DEPARTMENT IN (7130) THEN 'Administrative Services Bureau'
ELSE ','
END As Bureau
,L1.FIRST_NAME
,L1.MIDDLE_NAME
,L1.LAST_NAME
FROM [SOOPS-LAWREPT].[LAWDATA].dbo.EMPLOYEE L1
JOIN [SOOPS-LAWREPT].[LAWDATA].dbo.DEPTCODE L2 ON L1.Department =
L2.Department
JOIN [SOOPS-LAWREPT].[LAWDATA].dbo.JOBCODE L3 on L1.JOB_CODE = L3.JOB_CODE
JOIN [SOOPS-LAWREPT].[LAWDATA].dbo.PRSYSTEM P1 ON L1.PROCESS_LEVEL =
p1.PROCESS_LEVEL
WHERE L1.EMP_STATUS='A1'
-- Select the Return Value
-------------------------------
IF (#AssignmentType = 'FirstName')
BEGIN
SET #ReturnValue = (SELECT TOP 1 LTRIM(RTRIM(t.MiddleName)) From #EIDTemp t
where EID = #EID);
END
IF (#AssignmentType = 'MiddleName')
BEGIN
SET #ReturnValue = (SELECT TOP 1 LTRIM(RTRIM(t.MiddleName)) From #EIDTemp t
where EID = #EID);
END
IF (#AssignmentType = 'LastName')
BEGIN
SET #ReturnValue = (SELECT TOP 1 LTRIM(RTRIM(t.LastName)) From #EIDTemp t
where EID = #EID);
END
The problem is how you are setting your variables. When you use SET it will change the value to NULL if no rows are returned.
You should instead change up your code so it does something like this.
SET #ReturnValue = 'Unknown'
IF (#AssignmentType = 'FirstName')
BEGIN
SELECT #ReturnValue = LTRIM(RTRIM(t.MiddleName)) From #EIDTemp t
where EID = #EID
END
This sets an initial value to Unknown. This would be before all of your IF statements and would work across the whole collection. If there are no rows returned the value will remain unchanged. I removed the TOP 1 because it is not needed. If you have multiple rows it will receive the value from the last row in the result set. If there are lots of rows you could always use MAX or MIN.
#Perry, is the following more like what you are looking for:
WITH employee_ids AS
(
SELECT
emp.Employee AS eid
,P1.NAME As Section
,CASE
WHEN emp.DEPARTMENT IN (7010) THEN
'Legal Services Division'
WHEN emp.DEPARTMENT IN (7030,7040) THEN
'Fiscal Management Division'
ELSE
'Other'
END AS Division
,CASE
WHEN emp.DEPARTMENT IN (7130) THEN
'Administrative Services Bureau'
ELSE
','
END As Bureau
,emp.FIRST_NAME
,emp.MIDDLE_NAME
,emp.LAST_NAME
,ROW_NUMBER() OVER (PARTITION BY emp.EMPLOYEE) AS eid_match
FROM
[SOOPS-LAWREPT].[LAWDATA].dbo.EMPLOYEE AS emp
INNER JOIN
[SOOPS-LAWREPT].[LAWDATA].dbo.DEPTCODE AS depts
ON (emp.Department = depts.Department)
INNER JOIN
[SOOPS-LAWREPT].[LAWDATA].dbo.JOBCODE AS jcs
ON (emp.JOB_CODE = jcs.JOB_CODE)
INNER JOIN
[SOOPS-LAWREPT].[LAWDATA].dbo.PRSYSTEM AS prs
ON (emp.PROCESS_LEVEL = prs.PROCESS_LEVEL)
WHERE
emp.EMP_STATUS='A1'
)
,provisional_results AS
(
SELECT
CASE #AssignmentType
WHEN 'FirstName' THEN
employee_ids.FirstName
WHEN 'MiddleName' THEN
employee_ids.MiddleName
WHEN 'LastName' THEN
employee_ids.LastName
ELSE
NULL
END AS provisional_return_value
FROM
(VALUES (0)) AS default_values(default_value)
LEFT JOIN
employee_ids
ON (employee_ids.eid = #eid)
AND (eid_match = 1)
)
SELECT
#ReturnValue = ISNULL(LTRIM(RTRIM(provisional_return_value)), 'UNKNOWN')
FROM
provisional_results
I haven't tested the code as I'm not at my desktop so excuse any small syntax errors, but it should achieve what you need.
You need to save the ##RowCount variable immediately after running the insert/select and return the variable. If you don't save the variable, another statement will eventually clear the rowcount...
Example:
--Variable to hold the rowcount
DECLARE #Count int = 0
...
Insert Into #EIDTemp
SELECT L1.Employee, P1.NAME As Section,
...
WHERE L1.EMP_STATUS='A1'
--Save the result
SELECT #Count=##RowCount
...
--Use the saved result
Case
When #Count > 0 Then LTRIM(RTRIM(t.FirstName)) Else 'UNKNOWN'
End
A co-worker of mine solved the problem by checking the value of the Employee ID at the start and returning UNKNOWN with this code
> DECLARE #EID int = 0
DECLARE #AssignmentType varchar(max) = 'FirstName'
DECLARE #ReturnValue varchar(max) = 'UNKNOWN'
DECLARE #EIDTemp TABLE(EID varchar(6), Section varchar(max), Division
varchar(max), Bureau varchar(max), FirstName varchar(max), MiddleName
varchar(max), LastName varchar(max));
if #EID = 0
goto done
-- Insert into a Temp Table
-------------------------------
Insert Into #EIDTemp
SELECT L1.Employee, P1.NAME As Section,
CASE
WHEN L1.DEPARTMENT IN (7010) THEN 'Legal Services Division'
WHEN L1.DEPARTMENT IN (7030,7040) THEN 'Fiscal Management
Division'
Else 'Other'
END AS Division,
CASE
WHEN L1.DEPARTMENT IN (7130) THEN 'Administrative Services Bureau'
ELSE ','
END As Bureau
,L1.FIRST_NAME
,L1.MIDDLE_NAME
,L1.LAST_NAME
FROM [SOOPS-LAWREPT].[LAWDATA].dbo.EMPLOYEE L1
JOIN [SOOPS-LAWREPT].[LAWDATA].dbo.DEPTCODE L2 ON L1.Department =
L2.Department
JOIN [SOOPS-LAWREPT].[LAWDATA].dbo.JOBCODE L3 on L1.JOB_CODE =
L3.JOB_CODE
JOIN [SOOPS-LAWREPT].[LAWDATA].dbo.PRSYSTEM P1 ON L1.PROCESS_LEVEL =
p1.PROCESS_LEVEL
WHERE L1.EMP_STATUS='A1' AND l1.EMPLOYEE = #EID
-- Select the Return Value
-------------------------------
IF (#AssignmentType = 'FirstName')
BEGIN
SET #ReturnValue = (SELECT TOP 1 LTRIM(RTRIM(t.FirstName)) From #EIDTemp
t where EID = #EID);
END
IF (#AssignmentType = 'MiddleName')
BEGIN
SET #ReturnValue = (SELECT TOP 1 LTRIM(RTRIM(t.MiddleName)) From
#EIDTemp t where EID = #EID);
END
IF (#AssignmentType = 'LastName')
BEGIN
SET #ReturnValue = (SELECT TOP 1 LTRIM(RTRIM(t.LastName)) From #EIDTemp
t where EID = #EID);
END
done:
print #ReturnValue
Related
User code I used the code to display the results
SELECT ( ROW_NUMBER() OVER (ORDER BY c.[exp] DESC)) as [rank], c.[name],c.[lv],c.[exp],
`ISNULL(b.[name],'n/a') [guild],
ISNULL(b.[icon],'none.jpg') [guild_icon],
c.[job],
CAST(
CASE
WHEN c.[login_time] > c.[logout_time]
THEN 'ON'
ELSE 'OFF'
END
AS VARCHAR ) AS [stat] FROM [Telecaster].[dbo].[Character] c
LEFT JOIN [Telecaster].[dbo].[GuildMember] a ON [sid] = a.[player_id]
LEFT JOIN [Telecaster].[dbo].[Guild] b ON b.[sid] = a.[guild_id]`
WHERE c.[permission] < 100 AND c.[name] NOT LIKE '%#%' AND c.[lv] < 300
Actual results
desired results
I want to delete the color code along with the brackets
SELECT ( ROW_NUMBER() OVER (ORDER BY c.[exp] DESC)) as [rank], CASE WHEN (c.[name] LIKE '%<%' AND c.[name] LIKE '%>%') THEN RIGHT(c.[name],LEN(c.[name])-CHARINDEX('>',c.[name])) ELSE c.[name] END [name],c.[lv],c.[exp],
ISNULL(b.[name],'n/a') [guild],
ISNULL(b.[icon],'none.jpg') [guild_icon],
c.[job],
CAST(
CASE
WHEN c.[login_time] > c.[logout_time]
THEN 'ON'
ELSE 'OFF'
END
AS VARCHAR ) AS [stat] FROM [Telecaster].[dbo].[Character] c
LEFT JOIN [Telecaster].[dbo].[GuildMember] a ON [sid] = a.[player_id]
LEFT JOIN [Telecaster].[dbo].[Guild] b ON b.[sid] = a.[guild_id]
WHERE c.[permission] < 100 AND c.[name] NOT LIKE '%#%' AND c.[lv] < 300
I assumed the color String format would be similar across the records.
I would create a scalar function to remove the tags. Here's fiddle on how to do it. You could just do a STUFF in your original query but there's no error checking like you can do in a function.
CREATE FUNCTION fn_StripColorCode (#InputString nvarchar(512))
RETURNS nvarchar(512)
AS
BEGIN
DECLARE #first int = -1;
DECLARE #last int = -1;
--Find the start and end tags.
SET #first = CHARINDEX('<#', #InputString, 1);
SET #last = CHARINDEX('>', #InputString, 1);
--If either start or end is not found, return original string.
IF (#first < 0 OR #last < 0)
RETURN #InputString;
--If the start tag is found after the end tag, return the original string.
IF (#first > #last)
RETURN #InputString;
--Remove the tag.
DECLARE #result nvarchar(512);
SET #result = STUFF(#InputString, 1, #Last, '');
RETURN #result;
END
;
DECLARE #testName nvarchar(50) = '<#ff00c0>ASTA';
SELECT dbo.fn_StripColorCode(#testName);
(No column name)
ASTA
fiddle
Here's how I would do it inline using STUFF. I cleaned up your code a bit:
SELECT
ROW_NUMBER() OVER (ORDER BY c.[exp] DESC) as [rank]
, CASE
WHEN (c.[name] LIKE '<#%' AND c.[name] LIKE '%>%')
THEN STUFF(c.[name],1,CHARINDEX('>',c.[name]),'')
ELSE c.[name]
END [name]
, c.[lv]
, c.[exp]
, ISNULL(b.[name],'n/a') [guild]
, ISNULL(b.[icon],'none.jpg') [guild_icon]
, c.[job]
, CASE
WHEN c.[login_time] > c.[logout_time]
THEN 'ON'
ELSE 'OFF'
END AS [stat]
FROM [Telecaster].[dbo].[Character] c
LEFT JOIN [Telecaster].[dbo].[GuildMember] a
ON [sid] = a.[player_id]
LEFT JOIN [Telecaster].[dbo].[Guild] b
ON b.[sid] = a.[guild_id]
WHERE c.[permission] < 100
AND c.[name] NOT LIKE '%#%'
AND c.[lv] < 300
I have this stored procedure for a course registration system I am working on. My intention is to return a value of -1 if the query returns a course which a student has not taken according to the course pre requisites.
The pre req table only has two columns; CourseID being the course and PreReqCourse_ID being the required course for that specified course. If the student has taken all pre req courses then it should return a value of 1. I keep getting a value of -1 even when I run the query for a student who has taken the required pre req courses. Any help would be much appreciated!
CREATE PROCEDURE CheckPreReq
#StudentID INT,
#CourseID INT
AS
DECLARE #theCount INT
IF EXISTS (SELECT *
FROM PreReq
INNER JOIN Student_History ON (PreReq.Course_ID = #CourseID)
WHERE Student_History.Course_ID != PreReq.PreReqCourse_ID
AND Student_History.Student_ID = #StudentID)
BEGIN
SET #theCount =-1
END
ELSE
BEGIN
SET #theCount = 1
END
RETURN #theCount
Would something like this work?
DECLARE #PreReqsTotal tinyint
DECLARE #PreReqsFulfilled tinyint
-- Count pre-req courses.
SELECT #PreReqsTotal = COUNT(*)
FROM PreReq
WHERE [CourseID] = #CourseId
-- Count how many fulfilled by student.
SELECT #PreReqsFulfilled = count(*)
FROM Student_History hist
JOIN PreReq pre
on hist.Course_ID = pre.PreReqCourse_ID
WHERE pre.CourseID = #CourseID
and hist.Student_ID = #StudentID
RETURN CASE WHEN #PreReqsTotal = #PreReqsFulfilled THEN 1 ELSE -1 END
...or something like this:
IF EXISTS
(
SELECT blah.*
FROM
(
SELECT pre.*
,[PreFulfilled] = CASE WHEN hist.Course_ID is null THEN 0 ELSE 1 END
FROM PreReq pre
LEFT JOIN
Student_History hist
on pre.PreReqCourse_ID = hist.Course_ID
and hist.Student_ID = #StudentID
WHERE pre.CourseID = #CourseID
) blah
WHERE blah.[PreFulfilled] = 0 -- Unfulfilled PreReq.
)
BEGIN
RETURN -1 -- Has an unfulfilled PreReq.
END
RETURN 1 -- No unfulfilled PreReqs.
You should JOIN the PreReq table with the Student_History on the the PreReq.PreReqCourse_ID and Student_History.CourseID columns (take a look at my example). Then your SP should work.
--create tmp example tables
IF OBJECT_ID('tempdb..#PreReq') IS NOT NULL DROP TABLE #PreReq
CREATE TABLE #PreReq(
CourseID int,
PreReqCourse_ID int
)
--insert Course 3 which depends on Course 2 and 1 in #PreReq
INSERT INTO #PreReq
values(3,2),(3,1)
IF OBJECT_ID('tempdb..#Student_History') IS NOT NULL DROP TABLE #Student_History
CREATE TABLE #Student_History(
CourseID int not null,
StudentID int not null
);
--insert Student 1 who has visited Course 1 and 2
insert into #Student_History
VALUES(1,1),(2,1)
--declare variables
DECLARE #CourseID AS INT = 3
,#StudentID AS INT = 1
--COUNT on how many Courses #CourseID depends
,#necessaryCourses AS INT
--COUNT on how many Courses the Student has taken
,#countTakenCourses AS INT
,#theCount AS INT
SET #necessaryCourses = (SELECT count(*) FROM #PreReq WHERE CourseID = #CourseID);
SET #countTakenCourses = (
SELECT count(*)
FROM #PreReq p
--JOIN with Student_History to check if the student has visited the necessary course
JOIN #Student_History h on p.PreReqCourse_ID = h.CourseID
WHERE p.CourseID = #CourseID AND h.StudentID = #StudentID
)
IF #necessaryCourses = #countTakenCourses
BEGIN
set #theCount = 1
END
ELSE
BEGIN
set #theCount = -1
END
SELECT #theCount AS theCount
I have this weird encounter using CASE in sql 2014.
This is my query:
SELECT (CASE WHEN dbo.GetFunctionAge(C.Birthdate) = 0
THEN '' ELSE dbo.GetFunctionAge(C.Birthdate)
END) AS Age
,dbo.GetFunctionAge(C.Birthdate)
,c.Birthdate
FROM Client C
WHERE ClientID = '34d0d845-e3a6-4078-8936-953ff3378eac'
this is the output:
Here is the GetFunctionAge function if you might ask.
IF EXISTS (
SELECT *
FROM dbo.sysobjects
WHERE ID = OBJECT_ID(N'[dbo].[GetFunctionAge]') AND
xtype in (N'FN', N'IF', N'TF'))
DROP FUNCTION [dbo].[GetFunctionAge]
GO
CREATE FUNCTION [dbo].[GetFunctionAge](#BirthDate DATETIME)
RETURNS INT
AS
BEGIN
DECLARE #Age INT
IF(#BirthDate = '1753-01-01 00:00:00.000')
BEGIN
SET #Age = 0
END
ELSE
BEGIN
SET #Age = DATEDIFF(hour,#BirthDate,GETDATE())/8766
END
RETURN #Age
END
GO
Question:
Why is Column Age in my output is 0which should be ''?
I added (No column name) to show that its output is 0 so my expected output base from my case condition is '' not 0
I didn't receive any error regarding inconsistency of data so why is case behaving like that?
Thanks for those who could clarify this to me.
SELECT
(CASE
WHEN a.ageint = 0 THEN ''
ELSE cast(a.ageint as varchar(3))
END) AS Age
, a.ageint
, c.Birthdate
FROM Client as C
CROSS APPLY (
SELECT
ISNULL(dbo.GetFunctionAge(C.Birthdate), 0) AS ageint
) AS a
WHERE ClientID = '34d0d845-e3a6-4078-8936-953ff3378eac'
;
You can cast it into varchar so you can return ' '.
SELECT (CASE WHEN dbo.GetFunctionAge(C.Birthdate) = 0
THEN '' ELSE Cast(dbo.GetFunctionAge(C.Birthdate) as varchar(5))
END) AS Age
,dbo.GetFunctionAge(C.Birthdate)
,c.Birthdate
FROM Client C
WHERE ClientID = '34d0d845-e3a6-4078-8936-953ff3378eac'
But If you wish to remain your Age column in data type int.
You could just use NULL instead of ' '
SQL is not my best thing but I have been trying to optimize this stored procedure. It had multiple scalar-valued functions that I tried to change to table-valued functions because I read in many places that it's a more efficient way of doing it. And now I have them made but not real sure how to implement or if I maybe just didn't create them correctly.
This is the function I'm calling.
Alter FUNCTION [IsNotSenateActivityTableValue]
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
returns #T table(result varchar(max))
as
begin
DECLARE #result varchar(max);
declare #countcodes int;
declare #ishousebill int;
select #ishousebill = count(billid)
from BillMaster
where BillID = #BillID and Chamber = 'H'
If (#ishousebill = 0)
begin
SELECT #countcodes = count([ActivityCode])
FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%' and ActivityType = 'S'
and [ActivityCode] = #ActivityCode
if (#countcodes = 0)
begin
set #result = 'test'
end
else
begin
set #result = 'test2'
end
end
else
begin
set #result = #TextToDisplay
end
RETURN
END
And this is how I was trying to call them like this. I would prefer just being able to put them in the top but really anything that works would be good.
SELECT distinct
ActionDates.result as ActionDate
,ActivityDescriptions.result as ActivityDescription
FROM BillWebReporting.vwBillDetailWithSubjectIndex as vw
left outer join [BillWebReporting].[HasHouseSummary] as HasSummary on vw.BillID = HasSummary.BillID
outer APPLY dbo.IsNotSenateActivityDateTableValue(ActivityCode,vw.BillID,[ActionDate]) ActionDates
OUTER APPLY dbo.IsNotSenateActivityTableValue(ActivityCode,vw.BillID,[ActivityDescription]) as ActivityDescriptions
Getting a count just to see if at least one row exists is very expensive. You should use EXISTS instead, which can potentially short circuit without materializing the entire count.
Here is a more efficient way using an inline table-valued function instead of a multi-statement table-valued function.
ALTER FUNCTION dbo.[IsNotSenateActivityTableValue] -- always use schema prefix!
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
RETURNS TABLE
AS
RETURN (SELECT result = CASE WHEN EXISTS
(SELECT 1 FROM dbo.BillMaster
WHERE BillID = #BillID AND Chamber = 'H'
) THEN #TextToDisplay ELSE CASE WHEN EXISTS
(SELECT 1 FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%'
and ActivityType = 'S'
and [ActivityCode] = #ActivityCode
) THEN 'test2' ELSE 'test' END
END);
GO
Of course it could also just be a scalar UDF...
ALTER FUNCTION dbo.[IsNotSenateActivityScalar] -- always use schema prefix!
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #result VARCHAR(MAX);
SELECT #result = CASE WHEN EXISTS
(SELECT 1 FROM dbo.BillMaster
WHERE BillID = #BillID AND Chamber = 'H'
) THEN #TextToDisplay ELSE CASE WHEN EXISTS
(SELECT 1 FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%'
and ActivityType = 'S'
and [ActivityCode] = #ActivityCode
) THEN 'test2' ELSE 'test' END
END;
RETURN (#result);
END
GO
Table-valued functions return a table, in which, like any other table, rows have to be inserted.
Instead of doing set #result = ....., do:
INSERT INTO #T (result) VALUES ( ..... )
EDIT: As a side note, I don't really understand the reason for this function to be table-valued. You are essentially returning one value.
First of all UDFs generally are very non-performant. I am not sure about MySQL, but in Sql Server a UDF is recompiled every time (FOR EACH ROW OF OUTPUT) it is executed, except for what are called inline UDFs, which only have a single select statement, which is folded into the SQL of the outer query it is included in... and so is only compiled once.
MySQL does have inline table-valued functions, use it instead... in SQL Server, the syntax would be:
CREATE FUNCTION IsNotSenateActivityTableValue
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
RETURNS TABLE
AS
RETURN
(
Select case
When y.bilCnt + z.actCnt = 0 Then 'test'
when y.bilCnt = 0 then 'test2'
else #TextToDisplay end result
From (Select Count(billId) bilCnt
From BillMaster
Where BillID = #BillID
And Chamber = 'H') y
Full Join
(Select count([ActivityCode]) actCnt
From [HouseCoreData].[dbo].[ActivityCode]
Where ActivityDescription not like '%(H)%'
And ActivityType = 'S'
And [ActivityCode] = #ActivityCode) z
)
GO
I have a situation where I need to process and finally insert 1000s of records from a temptable into a database table. Before each insert, I need to ensure that conditions are met and right after each insert, I need to update a second table in my database. My problem is that currently, it takes approximately 25 minutes to run the query and I would like to drastically cut that time so my application can be more responsive. How can I go about doing this please?
DECLARE #rowcounter as INTEGER
CREATE TABLE #temporary_phonetable
(
rownumber int not null identity(1,1),
record_no BIGINT,
phone_name BIGINT,
phone_number Varchar(25) not null ,
responsemessage Varchar(200) not null ,
messagepriority Varchar(14) not null ,
phone_id BIGINT,
AD_show BIGINT,
power_show Varchar(400),
service_provider VARCHAR(30),
Phone_flag VARCHAR(30),
questionMessage BIGINT,
PRIMARY KEY (phone_id, phone_number, rownumber)
,UNIQUE (questionMessage, record_no, rownumber)
)
--GET PHONE DATA
--if phone numbers are sent in from the client, then we want to process those instead
IF ( ( ( #listofphones IS NULL OR LEN(#listofphones) <1) AND LEN(#peoplegroups) >0) )
BEGIN
--NO PHONENUMBER BUT THERE ARE GROUPS AVAILABLE
INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show, responsemessage)
SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE #includegreetings WHEN 1 THEN LTRIM(RTRIM(phone_name)) + #responsemessages
ELSE #responsemessages END as text_message
FROM user u WITH(NOLOCK)
INNER JOIN Phonenumbers n WITH(NOLOCK) ON n.user_no = u.user_no
INNER JOIN PeopleGroupRelations g ON g.phone_id=n.phone_id
INNER JOIN ( Select items FROM Split(#peoplegroups, #listofphonesdelimiter)) gg ON g.group_no = gg.items
WHERE n.user_no=#userid
AND n.status=''active''
SET #rowcounter = ##ROWCOUNT
END
ELSE IF ( LEN(#listofphones) >1 AND LEN(#peoplegroups) >0)
BEGIN
--PHONENUMBER AND GROUPS
INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show, responsemessage)
SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE #includegreetings WHEN 1 THEN LTRIM(RTRIM(phone_name)) + #responsemessages
ELSE #responsemessages END as text_message
FROM Split(#listofphones, ''|'') s
INNER JOIN PhoneNumbers n WITH(NOLOCK) ON n.phone_number = s.items
INNER JOIN User u WITH(NOLOCK) ON n.user_no =u.user_no
INNER JOIN PeoplegroupRelations g ON g.phone_id=n.phone_id
INNER JOIN ( Select items FROM Split(#peoplegroups, #listofphonesdelimiter)) gg ON g.group_no = gg.items
WHERE n.user_no=#userid
AND n.status=''active''
SET #rowcounter = ##ROWCOUNT
END
ELSE IF ( LEN(#listofphones) >1 AND LEN(#peoplegroups) >0)
BEGIN
--PHONENUMBER AND NO GROUPS
INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show, responsemessage)
SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE #includegreetings WHEN 1 THEN LTRIM(RTRIM(phone_name)) + #responsemessages
ELSE #responsemessages END as text_message
FROM Split(#listofphones, ''|'') s
INNER JOIN PhoneNumbers n WITH(NOLOCK) ON n.phone_number = s.items
INNER JOIN User u WITH(NOLOCK) ON n.user_no =u.user_no
INNER JOIN PeopleGroupRelations g ON g.phone_id=n.phone_id
INNER JOIN ( Select items FROM Split(#peoplegroups, #listofphonesdelimiter)) gg ON g.group_no = gg.items
WHERE n.user_no=#userid
AND n.status=''active''
SET #rowcounter = ##ROWCOUNT
END
ELSE
BEGIN
-- NO PHONENUMBER NO GROUP --- IE. SEND TO ALL PHONE NUMBERS
INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show,responsemessage)
SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE #includegreetings WHEN 1 THEN LTRIM(RTRIM(phone_name)) + #responsemessages
ELSE #responsemessages END as text_message
FROM User u
INNER JOIN PhoneNumbers n ON n.user_no = u.user_no
WHERE
n.status=''active''
AND n.user_no=#userid
SET #rowcounter = ##ROWCOUNT
END
IF( #rowcounter>0)
BEGIN
DECLARE #service_provider as Varchar(30)
DECLARE #PhoneType as Varchar(30)
IF (LOWER(RTRIM(LTRIM(#sendresponseswhen))) ='now')
BEGIN
SET #dateresponsessent = GETDATE()
END
DECLARE #rownumber int
DECLARE #power_show BIT
DECLARE #AD_show BIT
set #rownumber = 0
WHILE #rownumber < #rowcounter
BEGIN
set #rownumber = #rownumber + 1
-- THE VARIABLES
DECLARE #record_no as BIGINT
DECLARE #phone_name VARCHAR(30)
DECLARE #messagepriority as INTEGER
DECLARE #phone_number VARCHAR(30)
DECLARE #phone_id BIGINT
DECLARE #questionMessage BIGINT
SELECT
#phone_name = n.phone_name, #phone_number =n.phone_number, #messagepriority =n.messagepriority, #phone_id=n.phone_id ,
#AD_show=n.AD_show, #power_show=n.power_show
FROM
#temporary_phonetable n WITH(NOLOCK)
WHERE n.rownumber = #rownumber
SET #record_no = AddMessageToQueue(#phone_number, #responsemessages, #dateresponsessent, #savednames, #userid, un.messagepriority, #responsetype,
un.AD_show, un.power_show, #service_provider, #PhoneType)
If(#questionid > 0)
BEGIN
SET #questionMessage = AddQuestionMessage(#questionid,#phone_id, #record_no, DATEADD(d, 30, GETDATE()) )
END
UPDATE #temporary_phonetable SET record_no = #record_no, questionMessage=#questionMessage WHERE phone_number = #phone_number AND rownumber = #rownumber
END
IF( #power_show >0)
BEGIN
SET #responsemessages = #responsemessages + dbo.returnPoweredBy()
END
IF( #AD_show > 0)
BEGIN
SELECT #responsemessages = #responsemessages + CASE
WHEN (LEN(#responsemessages) + 14)< 160 THEN dbo.returnAD(#responsemessages)
ELSE '''' END
END
RETURN #rowcounter
END
I believe this is the place where the bulk of the issue resides.
WHILE #rownumber < #rowcounter
BEGIN
set #rownumber = #rownumber + 1
-- THE VARIABLES
DECLARE #record_no as BIGINT
DECLARE #phone_name VARCHAR(30)
DECLARE #messagepriority as INTEGER
DECLARE #phone_number VARCHAR(30)
DECLARE #phone_id BIGINT
DECLARE #questionMessage BIGINT
SELECT
#phone_name = n.phone_name, #phone_number =n.phone_number, #messagepriority =n.messagepriority, #phone_id=n.phone_id ,
#AD_show=n.AD_show, #power_show=n.power_show
FROM
#temporary_phonetable n WITH(NOLOCK)
WHERE n.rownumber = #rownumber
SET #record_no = AddMessageToQueue(#phone_number, #responsemessages, #dateresponsessent, #savednames, #userid, un.messagepriority, #responsetype,
un.AD_show, un.power_show, #service_provider, #PhoneType)
If(#questionid > 0)
BEGIN
SET #questionMessage = AddQuestionMessage(#questionid,#phone_id, #record_no, DATEADD(d, 30, GETDATE()) )
END
UPDATE #temporary_phonetable SET record_no = #record_no, questionMessage=#questionMessage WHERE phone_number = #phone_number AND rownumber = #rownumber
END
Add a unique constraint to rownumber in your temp table. Rewrite the WHILE as a CTE. Use APPLY to call the functions.
You also might want to consider using a table variable rather than a temporary table. You won't be writing to the tempdb and as table variables are created in memory they're faster.
This article has a nice comparison.