Related
I write this query in SQL Server 2016:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[s2_GetReceivedDocumentsCount]
#_Username NVARCHAR(MAX),
#_SearchText NVARCHAR(MAX),
#_States NVARCHAR(MAX),
#_Senders NVARCHAR(MAX),
#_Date1 NVARCHAR(MAX),
#_Date2 NVARCHAR(MAX),
#_Filter1ID NVARCHAR(MAX),
#_Filter1Value NVARCHAR(MAX)
AS
BEGIN
--https://blogs.technet.microsoft.com/mdegre/2011/11/06/what-is-parameter-sniffing/
DECLARE #Username NVARCHAR(MAX)
DECLARE #Fild BIT
DECLARE #SearchText NVARCHAR(MAX)
DECLARE #States NVARCHAR(MAX)
DECLARE #Senders NVARCHAR(MAX)
DECLARE #Date1 NVARCHAR(MAX)
DECLARE #Date2 NVARCHAR(MAX)
DECLARE #Filter1ID NVARCHAR(MAX)
DECLARE #Filter1Value NVARCHAR(MAX)
SELECT
#Username = #_Username,
#SearchText = #_SearchText,
#States = #_States,
#Senders = #_Senders,
#Date1 = #_Date1,
#Date2 = #_Date2,
#Filter1ID = #_Filter1ID,
#Filter1Value = #_Filter1Value
SELECT #SearchText = LTRIM(RTRIM(IsNull(#SearchText, '')))
SELECT #Filter1ID = LTRIM(RTRIM(IsNull(#Filter1ID, '')))
SELECT #Filter1Value = LTRIM(RTRIM(IsNull(#Filter1Value, '')))
DECLARE #PersonalPostID INT = NULL
SELECT #PersonalPostID = p.PostID
FROM Person pr
JOIN PersonPost pp ON pp.PersonID = pr.PersonID
JOIN Post p ON p.PostID = pp.PostID
WHERE pr.Username = #Username
AND p.IsPersonalPost = 1
DECLARE #independentPostExists BIT = CASE
WHEN EXISTS (SELECT 1 FROM Post t
WHERE t.Independent = 1 AND t.PostID > 0)
THEN 1
ELSE 0
END
DECLARE #temp0 TABLE (
DocumentID int
, Likeness int
, ParentScrutinyID int
)
;With AllPost
As
(
Select pp.PostID
From
PersonPost pp
Join Person prs On prs.PersonID = pp.PersonID
Where prs.Username = #Username
Union
Select [type].PostID
From
Post [type]
Join Post p On p.TypeID = [type].PostID
Join PersonPost pp On pp.PostID = p.PostID
Join Person prs On prs.PersonID = pp.PersonID
Where prs.Username = #Username
)
,
SplitSearchText
AS
(
Select * From dbo._1001_Split(dbo.ReplaceYK(#SearchText),N'')
),
Temp0
AS
(
Select Distinct
s.DocumentID
, s.Code
, s2_Scrutiny.ParentScrutinyID
From
s2_Document s
Join s2_State state On state.StateID = s.StateID
Join Post sender On sender.PostID = s.SenderID
Join s2_Scrutiny On
s2_Scrutiny.DocumentID = s.DocumentID
And s2_Scrutiny.IsActive = 1
And s2_Scrutiny.ReferenceID not in (-10, -20)
Cross Join AllPost
Join s2_Producer On s2_Producer.DocumentID = s.DocumentID
Join PersonPost producerPost On producerPost.PostID = s2_Producer.PostID
Join Person producerPerson On producerPerson.PersonID = producerPost.PersonID
Where
1 = 1
And (#States = '' Or (N',' + #States + N',') Like (N'%,' + Cast(s.StateID as nvarchar(max)) + ',%'))
And (#Senders = '' Or (N',' + #Senders + N',') Like (N'%,' + Cast(s.SenderID as nvarchar(max)) + ',%'))
And (#Date1 = '' Or s.RegistrationDate >= #Date1)
And (#Date2 = '' Or s.RegistrationDate <= #Date2)
And (#Filter1ID = ''
Or Exists(
Select 1
From
s2_FieldValue fv
Join s2_Field f On f.FieldID = fv.FieldID
Where
fv.DocumentID = s.DocumentID
And fv.FieldID = #Filter1ID
And (
(f.FieldTypeID in (0, 5/*فیلد محاسباتی*/) And fv.[Value] = #Filter1Value)
Or (f.FieldTypeID = 3 And Cast(fv.[FieldOptionID] as nvarchar(max)) = #Filter1Value)
Or (f.FieldTypeID in(1,2,4))
)
))
--پیشنهاد به پست یا نوع پستی که این شخص حائز آن است، ارجاع شده است
And AllPost.PostID = s2_Scrutiny.ReferenceID
), Temp1
AS
(
Select Distinct
s.DocumentID
,Likeness = 99999999
From Temp0 s
Where #SearchText != '' And #SearchText = ISNULL(s.Code, s.DocumentID)
Union
Select Distinct
s.DocumentID
,Likeness = SUM(ts.[Length])
From
Temp0 s
Join s2_TextSegment ts On
ts.TableName = N's2_Document'
And ts.FieldName = N'Subject'
And ts.RecordID = s.DocumentID
Where #SearchText != '' And #SearchText != ISNULL(s.Code, s.DocumentID)
Group by s.DocumentID
Union
Select Distinct
s.DocumentID
,Likeness = 1
From Temp0 s
Where #SearchText = ''
)
, Temp2
AS
(
Select t0.*, t1.Likeness
From
Temp0 t0
Join Temp1 t1 On t0.DocumentID = t1.DocumentID
)
Insert Into #temp0 (DocumentID, Likeness, ParentScrutinyID)
Select DocumentID, Likeness, ParentScrutinyID From Temp2
DECLARE #temp1 TABLE (
DocumentID int
, Likeness int
)
If #independentPostExists = 0
Begin
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
End
ELSE
Begin--حوزه مستقلی تعریف شده باشد
--انتقال حوزه فعال باشد
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
Join s2_Scrutiny parentScrutiny On parentScrutiny.ScrutinyID = t.ParentScrutinyID
Join s2_ScrutinyItem sci On sci.ScrutinyItemID = parentScrutiny.ScrutinyItemID
Where
sci.TransferArea = 1
-- شخص جاری در حوزه ارجاع دهنده باشد
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
Join s2_Scrutiny parentScrutiny On parentScrutiny.ScrutinyID = t.ParentScrutinyID
Join Temp_SubalternPost tsp1 On tsp1.Subaltern_PostID = parentScrutiny.ScrutinierID
Join Temp_SubalternPost tsp2 On tsp2.Superior_PostID = tsp1.Superior_PostID
Where
tsp1.Superior_NearestIndependent = 1
And tsp2.Subaltern_PostID = #PersonalPostID
--And Not Exists(Select 1 From #temp0 tt Where tt.DocumentID = t.DocumentID)
End
Select Count(Distinct t.DocumentID) From #temp1 t Where Likeness > 0
END--end procedure
GO
This code takes 26 seconds:
exec sp_executesql N'Exec [dbo].[s2_GetReceivedDocumentsCount] #username=N'admin', #Filter1ID=N'12',#Filter1Value=N'17658'
BUT :
I tested this code for another state but returned 22,000 records in 3 seconds
exec sp_executesql N'Exec [dbo].[s2_GetReceivedDocumentsCount] #username=N'admin'
In this code I removed the #Filter1ID=N'12',#Filter1Value=N'17658'
When I remove this #Filter1ID it not enter here:
And (#Filter1ID = ''
Or Exists(
Select 1
From
s2_FieldValue fv
Join s2_Field f On f.FieldID = fv.FieldID
Where
fv.DocumentID = s.DocumentID
And fv.FieldID = #Filter1ID
And (
(f.FieldTypeID in (0, 5/*فیلد محاسباتی*/) And fv.[Value] = #Filter1Value)
Or (f.FieldTypeID = 3 And Cast(fv.[FieldOptionID] as nvarchar(max)) = #Filter1Value)
Or (f.FieldTypeID in(1,2,4))
)
))
Now I'm sure problem is here. But where is it? Where is the problem?
While correlated EXISTS clauses can be a real problem, your overall SP is such a dogs breakfast that I think you should focus on other aspects first:
Do not use LIKE to match a list of numeric values:
(N',' + #States + N',') Like (N'%,' + Cast(s.StateID as nvarchar(max)) + ',%'))
Since you already utilise string splitting function, you should split input value into a table variable of stateIDs (make sure that data type is the same as s.StateID and join it. Do the same for #Senders.
Minimise the use of OR as this kills performance really quickly:
This And (#Date1 = '' Or s.RegistrationDate >= #Date1) should be replaced by:
SET #Date1 = CASE WHEN '' THEN '01-Jan-1753' ELSE #Date1 END and then in your query you can simply have And s.RegistrationDate >= #Date1.
For #Date2 use the maximum value as per DATETIME reference.
Get rid of NVARCHAR( MAX ). Unless you realistically expect input values to be more than 4000 characters, you should use NVARCHAR( 2000 ) or something smaller.
There is a major performance difference between UNION and UNION ALL. Make sure you use UNION ALL unless you need to remove duplicate records. See this
And lastly EXISTS: without fully knowing your table structure and being able to run the query myself I cannot see a way of removing it, such that it will definitely improve performance.
I have one SP for mobile application chat app (used with API) it has 25 filters and 10 tables join and return posts for user, it works good for 2 days but after 2 days it stop working, then i need to refresh it again with alter query or something then it start working for next few days.
If filter stop for any particular user than why others have issue with SP.
USE [DatabaseName]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROC [dbo].[uspGetShoutouts] (
#UserId UNIQUEIDENTIFIER,
#anotherUserid UNIQUEIDENTIFIER,
#Interest NVARCHAR(100),
#Gender NVARCHAR(100),
#AgeFrom INT,
#AgeTo INT,
#StartLatitude NUMERIC(20,15),
#StartLongitude NUMERIC(20,15),
#Radius FLOAT,
#Location BIT = NULL,
#IsTraveler BIT,
#IsLocal BIT,
#HomeTownCity VARCHAR(100),
#UserName NVARCHAR(200),
#FirstName NVARCHAR(200),
#LastName NVARCHAR(200),
#CreatedDate DATETIME,
#IsMyShoutout BIT,
#ShoutoutTypeId INT=0,
#PostTypeId INT=0,
#oldMoment BIT,
#SortExpression CHAR(1) = 1,
#CurrentPage INT = 1,
#PageSize INT = 10,
#IsFriend BIT=0,
#IsPrivate BIT,
#GroupId NVARCHAR(200),
#TotalRows INT OUTPUT
)
AS
BEGIN
DECLARE #UserList TABLE(
UserId uniqueidentifier,
FirstName NVARCHAR(100),
LastName NVARCHAR(100),
QuickBloxId NVARCHAR(100),
SocialId NVARCHAR(100),
Gender char(1),
Email NVARCHAR(100),
IsProfileImageSync bit,
IsFriend bit,
IsRequestSent bit,
RequestSender NVARCHAR(100),
IsBlocked bit,
FriendBlocked bit,
Age int,
HomeTownCity NVARCHAR(100),
ImageName NVARCHAR(200),
Distance numeric(20,6),
DistanceTemp numeric(20,6),
LastActiveDateTime datetime,
ShoutoutGuid uniqueidentifier,
ShoutoutId bigint not null,
InterestId int,
InterestName NVARCHAR(100),
ShoutoutImageName NVARCHAR(200),
Description NVARCHAR(max),
CreatedOn DateTime,
IsImageSync bit,
DisplayUpdatedOn NVARCHAR(50),
ShoutoutCity NVARCHAR(500),
ShoutoutCountry NVARCHAR(500),
AdministrativeAreaLevel1 NVARCHAR(500),
PlaceId NVARCHAR(500),
FormattedAaddress NVARCHAR(500),
Url NVARCHAR(500),
TotalLike int,
TotalComment int,
Selflike bit,
ShoutoutTypeId int,
ShoutoutType NVARCHAR(200),
PostTypeId int,
PostTypeName NVARCHAR(200),
oldMoment bit,
UserLatitude numeric(20,6),
UserLongitude numeric(20,6),
ShoutoutLatitude numeric(20,6),
ShoutoutLongitude numeric(20,6),
DistanceShoutoutMiles numeric(20,6)
)
SET NOCOUNT ON;
DECLARE #StartLatitude1 numeric(20,2) = #StartLatitude
DECLARE #StartLongitude1 numeric(20,2) =#StartLongitude;
;with
UserList as (
select
distinct
USRSHTOUT.ShoutoutId,
USRSHTOUT.ShoutoutGuid,
U.UserId,
U.FirstName,
U.LastName,
U.QuickbloxId,
convert(int,round(datediff(hour,dob,getdate())/8766.0,0)) as Age,
U.SocialId,
U.Gender,
U.Email,
isnull(U.IsProfileImageSync,0) IsProfileImageSync,
U.HomeTownCity,
U.ImageName,
isnull(fr.IsFriend,0) as IsFriend,
isnull(fr.IsRequestSent,0) as IsRequestSent,
isnull(fr.RequestSender,cast(cast(0 as binary) as uniqueidentifier)) as RequestSender,
isnull(fr.IsBlocked,0) as IsBlocked,
isnull(fr.FriendBlocked,0) as FriendBlocked,
[dbo].[fnCalcDistanceKM](cast(#StartLatitude1 as float),cast(#StartLongitude1 as float),cast (isnull(USRSHTOUT.Latitude,0) as float) ,cast(isnull(USRSHTOUT.Longitude,0) as float)) as Distance,
(geography::Point(coalesce(USRSHTOUT.Latitude,0), coalesce(USRSHTOUT.Longitude,0), 4326).STDistance(geography::Point(#StartLatitude1, #StartLongitude1, 4326))/1000) as DistanceTemp,
ULAL.UpdatedOn as LastActiveDateTime,
0 as InterestId,
'' as InterestName,
isnull(USRSHTOUT.ImageName,'') 'ShoutoutImageName',
isnull(USRSHTOUT.Description,'') Description,USRSHTOUT.CreatedOn,IsImageSync,
isnull(format(UGL.UpdatedOn,'dd-MMM, yyyy HH:mm tt'),'') 'DisplayUpdatedOn',
isnull(ADC.locality,'')[ShoutoutCity],
isnull(ADC.country,'')[ShoutoutCountry],
isnull(ADC.administrative_area_level_1,'') [AdministrativeAreaLevel1],
isnull(ADC.place_id,'') [PlaceId],
isnull(ADC.formatted_address,'') FormattedAaddress,
isnull(ADC.url,'') Url,
isnull(lt.TotalLike, 0) as TotalLike,
isnull(ct.TotalComment, 0) as TotalComment,
isnull(lt.SelfLike, 0) as SelfLike,
SHT.ShoutoutTypeId,
isnull(SHT.Name,'') ShoutoutType,
UPT.PostTypeId,
isnull(UPT.Name,'') PostTypeName,
USRSHTOUT.oldMoment,
UGL.Latitude 'UserLatitude',
UGL.Longitude 'UserLongitude',
USRSHTOUT.Latitude 'ShoutoutLatitude',
USRSHTOUT.Longitude 'ShoutoutLongitude',
DistanceShoutoutMiles
from
Users U
inner join UserShoutouts USRSHTOUT on U.UserId=USRSHTOUT.UserId
left join UserLastActivityLog ULAL on ULAL.UserId=U.UserId
left join UserGeoLocation UGL on UGL.UserId=U.UserId
left join AddressShoutoutMapping ASMP on ASMP.ShoutoutId=USRSHTOUT.ShoutoutId
left join AddressComponents ADC on ADC.AddressComponentId=ASMP.AddressComponentId
left join [ShoutoutType] SHT on SHT.ShoutoutTypeId=isnull(USRSHTOUT.ShoutoutTypeId,0)
LEFT JOIN [UserPostType] UPT ON UPT.PostTypeId = ISNULL(USRSHTOUT.PostTypeId,0)
cross apply (select cos(radians(#StartLatitude1)) * cos(radians(USRSHTOUT.Latitude)) * cos(radians(USRSHTOUT.Longitude) - radians(#StartLongitude1)) + sin(radians(#StartLatitude1)) * sin(radians(USRSHTOUT.Latitude))) T(ACosInput)
cross apply (select ((3959 * acos(case when abs(ACosInput) > 1 then sign(ACosInput)*1 else ACosInput end)))) T2(DistanceShoutoutMiles)
left join (
select ItemId,
count(1) TotalLike,
cast(sum(case when UserId = #anotherUserid then 1 else 0 end) as bit) as SelfLike
from dbo.LikeDetails
where Liked=1 and LikeSourceId=1
group by ItemId) as lt on USRSHTOUT.ShoutoutId = lt.ItemId
left join (
select ParentId,
count(1) as TotalComment
from Comments
where CommentSourceId=1 and Comments.IsDeleted=0
group by ParentId) as ct on USRSHTOUT.ShoutoutId = ct.ParentId
left join dbo.tvf_GetFriendsByUserId (#UserId) fr on u.UserId = fr.ThisFriendId
left join UserShoutoutsPrivate USP on USP.ShoutoutId = USRSHTOUT.ShoutoutId
left join UserInterest UI on UI.InterestId = USP.GroupId
left join Interest INTRST on INTRST.Id = UI.InterestId
where
USRSHTOUT.IsDeleted=0
and (((#oldMoment = 0) and USRSHTOUT.oldMoment = #oldMoment)
or ((#oldMoment = 1) and USRSHTOUT.oldMoment = 1 or USRSHTOUT.oldMoment = 0) )
and U.IsEmailVerified=1 and isnull(U.IsDeactivated,0)=0
and (#ShoutoutTypeId=0 or USRSHTOUT.ShoutoutTypeId=#ShoutoutTypeId)
and (#IsMyShoutout=0 or (#IsMyShoutout=1 and USRSHTOUT.UserId = #UserId))
and ((#UserName is not null and #UserName='all'
OR ((U.FirstName + ' ' + U.LastName) = #UserName)OR (U.FirstName like LTRIM(RTRIM(#UserName))+'%') OR (U.LastName like LTRIM(RTRIM(#UserName))+'%'))
OR ( #FirstName is not null AND #LastName is null and
((U.FirstName = #FirstName ) OR (U.FirstName like LTRIM(RTRIM(#FirstName))+'%')))
OR ( #LastName is not null AND #FirstName is null and
((U.LastName = #LastName ) OR (U.LastName like LTRIM(RTRIM(#LastName))+'%')))
OR ((( #FirstName is not null AND #LastName is not null AND
((U.FirstName + ' ' + U.LastName) = #FirstName + ' ' + #LastName) OR (U.FirstName like LTRIM(RTRIM(#FirstName))+'%')) and (U.LastName like LTRIM(RTRIM(#LastName))+'%'))))
and((#Interest <>'' AND #IsPrivate = 1 AND (exists (select * from dbo.UserInterest where (UserId = U.UserId and InterestId in (select * from dbo.Split(#Interest,','))))
or #Interest ='')
or(#IsPrivate = 1
and (UI.Interestid in (select items from dbo.Split(#GroupId,',')) and INTRST.IsPrivate = 1 and INTRST.IsDelete = 0 and USRSHTOUT.IsDeleted=0 and
USP.ShoutoutId = USRSHTOUT.ShoutoutId and UI.IsActive = 1 and USP.GroupId in (select items from dbo.Split(#GroupId,','))))
)
OR(#Interest <>'' AND #IsPrivate = 0 AND (exists (select * from dbo.UserInterest where (UserId = U.UserId and InterestId in (select * from dbo.Split(#Interest,','))))
or #Interest ='')
or(#IsPrivate = 1
and (UI.Interestid in (select items from dbo.Split(#GroupId,',')) and INTRST.IsPrivate = 1 and INTRST.IsDelete = 0 and USRSHTOUT.IsDeleted=0 and
USP.ShoutoutId = USRSHTOUT.ShoutoutId and UI.IsActive = 1 and USP.GroupId in (select items from dbo.Split(#GroupId,','))))
)
OR(#Interest ='' AND #IsPrivate = 0 AND (exists (select * from dbo.UserInterest where (UserId = U.UserId and InterestId in (select * from dbo.Split(#Interest,','))))
or #Interest =''))
)
and (#PostTypeId=0 or USRSHTOUT.PostTypeId=#PostTypeId)
)
insert into #UserList
select
UserId,
FirstName,
LastName,
QuickBloxId,
SocialId,
Gender,
Email,
IsProfileImageSync,
IsFriend,
IsRequestSent,
RequestSender,
IsBlocked,
FriendBlocked,
Age,
HomeTownCity,
ImageName,
Distance,
DistanceTemp,
LastActiveDateTime,
ShoutoutGuid,
ShoutoutId,
InterestId,
InterestName,
ShoutoutImageName,
Description,
CreatedOn,
IsImageSync,
DisplayUpdatedOn,
ShoutoutCity,
ShoutoutCountry,
AdministrativeAreaLevel1,
PlaceId,
FormattedAaddress,
Url,
u.TotalLike,
u.TotalComment,
u.Selflike,
ShoutoutTypeId,
ShoutoutType,
PostTypeId,
PostTypeName,
oldMoment,
UserLatitude,
UserLongitude,
ShoutoutLatitude,
ShoutoutLongitude,
DistanceShoutoutMiles
from UserList u
where
(#Gender ='' or ((Gender in(select * from dbo.Split(#Gender,','))) or (#Gender like '%3%' and Gender=0)))
and(
((#AgeFrom = 18) AND ((#AgeTo= 65 and Age >= 15 )
or (Age >= 15 and Age <= #AgeTo)))
OR
((#AgeTo= 65 and Age >= #AgeFrom )
or (Age >= #AgeFrom and Age <= #AgeTo))
)
and IsBlocked <> 1
and FriendBlocked <> 1
and (#Location=0 or ((DistanceShoutoutMiles<= #Radius) or (#IsLocal=1 and HomeTownCity=#HomeTownCity)))
and (#IsFriend=0 or (#IsFriend=1 and IsFriend=1))
and (#Location=0 or (
((#IsTraveler=1 and #IsLocal=1) or (#IsTraveler=0 and #IsLocal=0)) or
((#IsTraveler=1 and #IsLocal=0 and lower(HomeTownCity) != lower(#HomeTownCity))
or (#IsTraveler=0 and #IsLocal=1 and lower(HomeTownCity) = lower(#HomeTownCity)))))OPTION(RECOMPILE)
set #TotalRows = ##rowcount
IF(#CurrentPage=0)
begin
select * from #UserList order by Distance asc OPTION(OPTIMIZE FOR UNKNOWN)
end
ELSE
BEGIN
declare #OffSetSize as bigint
set #OffSetSize = ((#CurrentPage * #PageSize) - #PageSize)
IF (#SortExpression = '1')
BEGIN
SELECT *
FROM #UserList
WHERE CreatedOn<#CreatedDate
ORDER BY CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE IF (#SortExpression = '2')
BEGIN
SELECT *
FROM #UserList
WHERE CreatedOn>#CreatedDate
ORDER BY CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE IF (#SortExpression = '3')
BEGIN
SELECT *
FROM #UserList
ORDER BY Distance ASC, CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE IF (#SortExpression = '4')
BEGIN
SELECT *
FROM #UserList
ORDER BY Distance ASC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE
BEGIN
SELECT *
FROM #UserList
ORDER BY CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
END
ENDGO
I have a stored procedure which returns result from two tables using outer join and where conditions. It has order by clause as well. I want to add paging to it so that only requested number of records are returned. How can I do it? I need to supply pagenumber, totalnumber of records, current page etc ? My stored procedure is:
CREATE PROCEDURE [dbo].[hr_SearchVacanciesForService]
#SearchText NVARCHAR(50) = NULL,
#DutyStationID INT = NULL,
#VacancyCategoryIDs VARCHAR(1000) = NULL,
#Language INT = 1
AS
SELECT *
FROM dbo.hr_Vacancies LEFT OUTER JOIN dbo.hr_DutyStations ON dbo.hr_Vacancies.DutyStationID = dbo.hr_DutyStations.DutyStationID
LEFT OUTER JOIN dbo.hr_Companies
ON dbo.hr_Vacancies.CompanyID = dbo.hr_Companies.CompanyID
WHERE dbo.hr_Vacancies.Deleted = 0
AND (dbo.hr_Vacancies.JobTitleLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.JobTitleLang2 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang2 LIKE #LoacalSeacrchText
AND (dbo.hr_Vacancies.DutyStationID = #DutyStationID OR #DutyStationID IS NULL OR #DutyStationID = 0)
ORDER BY HavePriority DESC, StartDate DESC, dbo.hr_Vacancies.VacancyID DESC
Use option with CTE and OVER() clause
CREATE PROCEDURE [dbo].[hr_SearchVacanciesForService]
#SearchText NVARCHAR(50) = NULL,
#DutyStationID INT = NULL,
#VacancyCategoryIDs VARCHAR(1000) = NULL,
#Language INT = 1,
#NumberOfPages int
AS
;WITH cte AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY HavePriority DESC, StartDate DESC, dbo.hr_Vacancies.VacancyID DESC) AS Pages
FROM dbo.hr_Vacancies LEFT OUTER JOIN dbo.hr_DutyStations ON dbo.hr_Vacancies.DutyStationID = dbo.hr_DutyStations.DutyStationID
LEFT OUTER JOIN dbo.hr_Companies ON dbo.hr_Vacancies.CompanyID = dbo.hr_Companies.CompanyID
WHERE dbo.hr_Vacancies.Deleted = 0
AND (dbo.hr_Vacancies.JobTitleLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.JobTitleLang2 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang2 LIKE #LoacalSeacrchText
AND (dbo.hr_Vacancies.DutyStationID = #DutyStationID OR #DutyStationID IS NULL OR #DutyStationID = 0)
)
SELECT *, COUNT(*) OVER() AS totalOfPages
FROM cte
WHERE Pages BETWEEN 1 AND ISNULL(#NumberOfPages, Pages)
Example using OVER() clause with expressions:
SELECT ... ROW_NUMBER() OVER (ORDER BY
CASE WHEN dbo.hr_Vacancies.Priority = 0
THEN 0 ELSE
CASE WHEN CONVERT(DATETIME,CONVERT(CHAR(10),dbo.hr_Vacancies.PriorityDateExpired,101)) > CONVERT(DATETIME,CONVERT(CHAR(10),GETDATE(),101)) OR dbo.hr_Vacancies.PriorityDateExpired IS NULL
THEN 1 ELSE 0 END END DESC, your_second_expression_StartDate DESC)
If you want to show records from 20 to 30:
CREATE PROCEDURE [dbo].[hr_SearchVacanciesForService]
#SearchText NVARCHAR(50) = NULL,
#DutyStationID INT = NULL,
#VacancyCategoryIDs VARCHAR(1000) = NULL,
#Language INT = 1,
#StartPage int = NULL,
#EndPage int = NULL
AS
;WITH cte AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY your_case_expressionForColumnHavePriority DESC, your_case_expressionForColumnStartDate DESC, dbo.hr_Vacancies.VacancyID DESC) AS Pages
FROM dbo.hr_Vacancies LEFT OUTER JOIN dbo.hr_DutyStations ON dbo.hr_Vacancies.DutyStationID = dbo.hr_DutyStations.DutyStationID
LEFT OUTER JOIN dbo.hr_Companies ON dbo.hr_Vacancies.CompanyID = dbo.hr_Companies.CompanyID
WHERE dbo.hr_Vacancies.Deleted = 0
AND (dbo.hr_Vacancies.JobTitleLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.JobTitleLang2 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang1 LIKE #LoacalSeacrchText
OR dbo.hr_Vacancies.DescriptionLang2 LIKE #LoacalSeacrchText
AND (dbo.hr_Vacancies.DutyStationID = #DutyStationID OR #DutyStationID IS NULL OR #DutyStationID = 0)
)
SELECT *, COUNT(*) OVER() AS totalOfPages
FROM cte
WHERE Pages BETWEEN ISNULL(#StartPage, Pages) AND ISNULL(#EndPage, Pages)
You can read the following papers :
SQL Server stored procedures to page large tables or queries
Or
Stored Procedure having Sorting, Paging and Filtering
OLD METHOD - Simple Pagination script with (limit,order direction,order column,start index)
#orderColumn int ,
#orderDir varchar(20),
#start int ,
#limit int,
#searchKey varchar(20)
declare #to as int = #start+#limit
select IDENTITY(int, 1, 1) AS SnoID,null as abc, make.link,make.manf,make.name
into #tempMake
from make where status=1 and UPPER(make.name) like upper('%'+#searchKey+'%')
select * from #tempMake where SnoID>#start and SnoID<=#to
order by
CASE WHEN #orderColumn = 1 AND #orderdir = 'desc' THEN #tempMake.[manf] END DESC,
CASE WHEN #orderColumn = 1 AND #orderdir = 'asc' THEN #tempMake.[manf] END ASC,
CASE WHEN #orderColumn = 2 AND #orderdir = 'desc' THEN #tempMake.[link] END DESC,
CASE WHEN #orderColumn = 2 AND #orderdir = 'asc' THEN #tempMake.[link] END ASC
select count(#tempMake.SnoID) as row_count from #tempMake
drop table #tempMake
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.
Can anybody help me to optimize this code? At present it takes 17 seconds.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
--SpResumeSearch NULL,null,null,null,null,null,null,null,null,null,null,NULL,null,null,null,null,null,null,null,0,10,NULL
ALTER PROCEDURE [dbo].[SpResumeSearch]
#Keyword varchar(50) = NULL,
#JobCategoryId int = NULL,
#NationalityId int = NULL,
#CountryId int = NULL,
#LocationId int = NULL,
#Email nvarchar(50) = NULL,
#Gender int = NULL,
#PassportNumber nvarchar(20) = NULL,
#VisaStatus int = NULL,
#PoBox nvarchar(10) = NULL,
#CareerLevelId int = NULL,
#KeySkills nvarchar(50) = NULL,
#ExpectedSalary int = NULL,
#Experience int = NULL,
#DOB varchar(20) = NULL,
#AppliedFrom datetime = NULL,
#AppliedTo datetime = NULL,
#MaritalStatusId int = NULL,
#LanguageId int = NULL,
#PageIndex int,
#NumRows int,
#SortCol varchar(20) = NULL
AS
BEGIN
DECLARE #startRowIndex INT;
SET #startRowIndex = (#PageIndex * #NumRows) + 1;
WITH ResumeListTemp AS
(SELECT DISTINCT M.MemberID, R.ResumeID, R.CreatedDate, R.ModifiedDate, R.CompletedDate, RP.FirstName, RP.LastName, G.Title AS Gender,
RP.DateOfBirth, C.NationalityTitle AS Nationality, RPD.KeySkills, RPD.ExperienceYear AS Experience, V.Title AS VisaStatus, RC.Phone, RC.Mobile,
ROW_NUMBER() OVER (ORDER BY
CASE WHEN #SortCol='FIRSTNAME' THEN FirstName END,
CASE WHEN #SortCol='LASTNAME' THEN RP.LastName END,
CASE WHEN #SortCol='GENDER' THEN G.Title END,
CASE WHEN #SortCol='DOB' THEN RP.DateOfBirth END,
CASE WHEN #SortCol='NATIONALITY' THEN C.NationalityTitle END,
CASE WHEN #SortCol='KEYSKILLS' THEN RPD.KeySkills END,
CASE WHEN #SortCol='EXPERIENCE' THEN RPD.ExperienceYear END,
CASE WHEN #SortCol='VISASTATUS' THEN V.Title END,
CASE WHEN #SortCol='CONTACTNO' THEN RC.Mobile END,
CASE WHEN #SortCol='UPDATEDATE' THEN R.ModifiedDate END,
CASE WHEN #SortCol IS NULL THEN R.CompletedDate END
) AS RowNum
FROM TblResume AS R
LEFT OUTER JOIN TblResumeContactInfo AS RC ON RC.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumePersonalDetail AS RP ON RP.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumeJobCategory AS RJC ON RJC.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumeProfessionalDetail AS RPD ON RPD.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumeWorkExperience AS RE ON RE.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumeEducation AS RQ ON RQ.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblResumeSkill AS RS ON RS.FKResumeID = R.ResumeID
LEFT OUTER JOIN TblMember AS M ON M.MemberID = R.FKMemberID
LEFT OUTER JOIN TblMasterGender AS G ON G.GenderID = RP.FKGenderID
LEFT OUTER JOIN TblMasterCountry AS C ON C.CountryID = RP.FKNationalityID
LEFT OUTER JOIN TblRisVisaStatus AS V ON V.VisaStatusID = RP.FKVisaStatusID
LEFT OUTER JOIN TblResumeLanguage AS L ON L.FKResumeID = R.ResumeID
WHERE (
-- RC.Address LIKE '%'+COALESCE(#Keyword,RC.Address)+'%' OR
-- RC.City LIKE '%'+COALESCE(#Keyword,RC.City)+'%' OR
R.ResumeID IN ( SELECT _RQ.FKResumeID FROM TblResumeEducation AS _RQ, TblResume AS _R WHERE _RQ.Specialization LIKE '%'+COALESCE(#Keyword, _RQ.Specialization)+'%' AND _RQ.FKResumeID=_R.ResumeID GROUP BY _RQ.FKResumeID) OR
R.ResumeID IN ( SELECT _RQ.FKResumeID FROM TblResumeEducation AS _RQ, TblResume AS _R WHERE _RQ.Institution LIKE '%'+COALESCE(#Keyword, _RQ.Institution)+'%' AND _RQ.FKResumeID=_R.ResumeID GROUP BY _RQ.FKResumeID) OR
RP.FirstName LIKE '%'+COALESCE(#Keyword,RP.FirstName)+'%' OR
RP.LastName LIKE '%'+COALESCE(#Keyword,RP.LastName)+'%' OR
--RP.PassportNumber LIKE '%'+COALESCE(#Keyword,RP.PassportNumber)+'%' OR
--(#Keyword IS NULL OR RP.PassportNumber LIKE '%' + #Keyword +'%') OR
RPD.Summary LIKE '%'+COALESCE(#Keyword,RPD.Summary)+'%' OR
-- R.ResumeID IN ( SELECT _RS.FKResumeID FROM TblResumeSkill AS _RS, TblResume AS _R WHERE _RS.Title LIKE '%'+COALESCE(#Keyword,_RS.Title)+'%' AND _RS.FKResumeID=_R.ResumeID GROUP BY _RS.FKResumeID) OR
-- R.ResumeID IN ( SELECT _RE.FKResumeID FROM TblResumeWorkExperience AS _RE, TblResume AS _R WHERE _RE.Employer LIKE '%'+COALESCE(#Keyword, _RE.Employer)+'%' AND _RE.FKResumeID=_R.ResumeID GROUP BY _RE.FKResumeID) OR
R.ResumeID IN ( SELECT _RE.FKResumeID FROM TblResumeWorkExperience AS _RE, TblResume AS _R WHERE _RE.Designation LIKE '%'+COALESCE(#Keyword, _RE.Designation)+'%' AND _RE.FKResumeID=_R.ResumeID GROUP BY _RE.FKResumeID) OR
R.ResumeID IN ( SELECT _RE.FKResumeID FROM TblResumeWorkExperience AS _RE, TblResume AS _R WHERE _RE.Responsibilities LIKE '%'+COALESCE(#Keyword, _RE.Responsibilities)+'%' AND _RE.FKResumeID=_R.ResumeID GROUP BY _RE.FKResumeID)) AND
R.ResumeID IN ( SELECT _RJC.FKResumeID FROM TblResumeJobCategory AS _RJC, TblResume AS _R WHERE _RJC.FKJobCategoryID = COALESCE(#JobCategoryId, _RJC.FKJobCategoryID) AND _RJC.FKResumeID=_R.ResumeID GROUP BY _RJC.FKResumeID ) AND
RP.FKNationalityID = COALESCE(#NationalityId, RP.FKNationalityID) AND
RC.FKCountryID = COALESCE(#CountryId, RC.FKCountryID) AND
-- RPD.FKJobLocationID = COALESCE(#LocationId, RPD.FKJobLocationID) AND
-- M.Email LIKE '%'+COALESCE(#Email, M.Email)+'%' AND
-- RP.FKGenderID = COALESCE(#Gender, RP.FKGenderID) AND
-- RP.PassportNumber LIKE '%'+COALESCE(#PassportNumber, RP.PassportNumber)+'%' AND
-- RP.FKVisaStatusID = COALESCE(#VisaStatus, RP.FKVisaStatusID) AND
-- COALESCE(RC.ZipCode,'0') LIKE '%'+COALESCE(#PoBox, COALESCE(RC.ZipCode,'0'))+'%' AND
RPD.FKExperienceLevelID = COALESCE(#CareerLevelId, RPD.FKExperienceLevelID) AND
-- RPD.KeySkills LIKE '%'+COALESCE(#KeySkills, RPD.KeySkills)+'%' AND
RPD.FKSalaryID = COALESCE(#ExpectedSalary, RPD.FKSalaryID) AND
RPD.ExperienceYear = COALESCE(#Experience, RPD.ExperienceYear) AND
RP.DateOfBirth = COALESCE(#DOB, RP.DateOfBirth) AND
R.CompletedDate = COALESCE(#AppliedFrom, R.CompletedDate) AND
R.CompletedDate = COALESCE(#AppliedTo, R.CompletedDate) AND
RP.FKMaritalStatusID = COALESCE(#MaritalStatusId, RP.FKMaritalStatusID) AND
R.ResumeID IN ( SELECT _L.FKResumeID FROM TblResumeLanguage AS _L, TblResume AS _R WHERE _L.FKLanguageID = COALESCE(#LanguageId, _L.FKLanguageID) AND _L.FKResumeID=_R.ResumeID GROUP BY _L.FKResumeID ) AND
R.IsCompleted = 1
)
SELECT ResumeListTemp.*, (SELECT COUNT(*) from ResumeListTemp) AS RecCount
FROM ResumeListTemp
WHERE RowNum BETWEEN #startRowIndex AND #StartRowIndex + #NumRows - 1
ORDER BY
CASE WHEN #SortCol='FIRSTNAME' THEN FirstName END,
CASE WHEN #SortCol='LASTNAME' THEN LastName END,
CASE WHEN #SortCol='GENDER' THEN Gender END,
CASE WHEN #SortCol='DOB' THEN DateOfBirth END,
CASE WHEN #SortCol='NATIONALITY' THEN Nationality END,
CASE WHEN #SortCol='KEYSKILLS' THEN KeySkills END,
CASE WHEN #SortCol='EXPERIENCE' THEN Experience END,
CASE WHEN #SortCol='VISASTATUS' THEN VisaStatus END,
CASE WHEN #SortCol='CONTACTNO' THEN Mobile END,
CASE WHEN #SortCol='UPDATEDATE' THEN ModifiedDate END,
CASE WHEN #SortCol IS NULL THEN CompletedDate END
END
try to replace * with the column names
In this case, I think that building your query dynamically and using sp_executesql will give you much better performance.
There's an MSDN article explaining the basics here, and there are some more in-depth articles by Erland Sommarskog, here and here.
Having '%' at the very start of a LIKE clause can cause a table scan, try to remove them if possible.
since there is only one column to be sorted in the result, you may try to replace the ORDER BY clause (twice!) as
CASE #SortCol
WHEN 'FIRSTNAME' THEN FirstName
WHEN 'LASTNAME' THEN LastName
etc
ELSE CompletedDate
END
(you probably need to CONVERT columns to NVARCHAR)
Optimization for WHERE section - seems to me, there is no need of using IN clause, thouse tables are already joined by ResumeID, all you need is to filter them out:
WHERE (
(RQ.Specialization IS NOT NULL AND (#Keyword IS NULL OR RQ.Specialization LIKE '%'+#Keyword+'%')) OR
(RQ.Institution IS NOT NULL AND (#Keyword IS NULL OR RQ.Institution LIKE '%'+#Keyword+'%')) OR
(RP.FirstName IS NOT NULL AND (#Keyword IS NULL OR RP.FirstName LIKE '%'+#Keyword+'%')) OR
(RP.LastName IS NOT NULL AND (#Keyword IS NULL OR RP.LastName LIKE '%'+#Keyword+'%')) OR
(RPD.Summary IS NOT NULL AND (#Keyword IS NULL OR RPD.Summary LIKE '%'+#Keyword+'%')) OR
(RE.Designation IS NOT NULL AND (#Keyword IS NULL OR RE.Designation LIKE '%'+#Keyword+'%')) OR
(RE.Responsibilities IS NOT NULL AND (#Keyword IS NULL OR RE.Responsibilities LIKE '%'+#Keyword+'%'))) AND
(RJC.FKJobCategoryID IS NOT NULL AND (#JobCategoryId IS NULL OR RE.Designation LIKE '%'+#JobCategoryId+'%')) AND
RP.FKNationalityID = COALESCE(#NationalityId, RP.FKNationalityID) AND
RC.FKCountryID = COALESCE(#CountryId, RC.FKCountryID) AND
RPD.FKExperienceLevelID = COALESCE(#CareerLevelId, RPD.FKExperienceLevelID) AND
RPD.FKSalaryID = COALESCE(#ExpectedSalary, RPD.FKSalaryID) AND
RPD.ExperienceYear = COALESCE(#Experience, RPD.ExperienceYear) AND
RP.DateOfBirth = COALESCE(#DOB, RP.DateOfBirth) AND
R.CompletedDate = COALESCE(#AppliedFrom, R.CompletedDate) AND
R.CompletedDate = COALESCE(#AppliedTo, R.CompletedDate) AND
RP.FKMaritalStatusID = COALESCE(#MaritalStatusId, RP.FKMaritalStatusID) AND
(L.FKLanguageID IS NOT NULL AND (#LanguageId IS NULL OR L.FKLanguageID LIKE '%'+#LanguageId+'%')) AND
R.IsCompleted = 1
)
Why are you starting each where clause with a wildcard? you can never optimize using that technique (even if you convert to dynamic SQL) as the database is not unable to use the indexes. Require your users to to at a minimum put in the first letter of what they are searching for.
Get rid of the subselects, they are performance killers. Since you are already joining to those tables, you shouldn't need them.