How to replace where clause with a function and use it in stored procedures? - sql

I have two stored procedures that they have the same where clause, one of them is use for pagination:
ALTER PROCEDURE [dbo].[ret_PayrollCalculations_GetPagedFilteredPersonnels]
(
#SortField varchar(512),
#PageNo int,
#PageSize int,
#CalculationCommandType int,
#StartWorkingPeriodId int,
#StartYear int,
#EndWorkingPeriodId int,
#EndYear int,
#Status int,
#SalariedGuid uniqueidentifier,
#SalariedType int,
#OfficeNumber varchar(64),
#SalariedResultSetId int,
#Keyword nvarchar(2024),
#OperationalUnitIds [dbo].[ListOfID] READONLY
)
AS
DECLARE #AccessibleSalariedGuids [dbo].[ListOfGuid]
IF EXISTS (SELECT * FROM #OperationalUnitIDs)
BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT FeatureGuid FROM prs_OperationalUnitFeatures
WHERE
OperationalUnitID in (SELECT * FROM #OperationalUnitIDs) AND
FeatureFlag IN (2,4)
END
ELSE BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT [Guid] FROM ret_vwSalaried
END
DECLARE #OffsetRows INT = CASE WHEN #PageNo = 1 THEN 0 ELSE (#PageNo - 1) * #PageSize END;
DECLARE #TotalCount INT;
WITH Result AS(
SELECT
CASE
WHEN #SortField = N'[FullName]' THEN ROW_NUMBER() OVER (ORDER BY salaried.[FullName])
WHEN #SortField = N'[FullName] DESC' THEN ROW_NUMBER() OVER (ORDER BY salaried.[FullName] DESC)
WHEN #SortField = N'[WorkingPeriodTitle]' THEN ROW_NUMBER() OVER (ORDER BY calcs.[Year],workingPeriods.[Index])
WHEN #SortField = N'[WorkingPeriodTitle] DESC' THEN ROW_NUMBER() OVER (ORDER BY calcs.[Year] DESC,workingPeriods.[Index] DESC)
WHEN #SortField = N'[PersonnelNo]' THEN ROW_NUMBER() OVER (ORDER BY salaried.[PersonnelNo])
WHEN #SortField = N'[PersonnelNo] DESC' THEN ROW_NUMBER() OVER (ORDER BY salaried.[PersonnelNo] DESC)
END AS [RowNumber],
calcs.[Guid],
calcs.[CalculationCommandGuid],
calcs.[SalariedGuid],
salaried.[PersonnelNo],
salaried.[FullName] AS [PersonnelFullName],
command.[Type] [CommandType],
salaried.[SalariedType],
workingPeriods.Title AS [WorkingPeriodTitle],
command.[MainYear] AS [Year],
command.[Approved],
command.[FinalApproved]
FROM
ret_PayrollCalculationCommands command INNER JOIN
ret_PayrollCalculations calcs ON calcs.[CalculationCommandGuid] = command.[Guid] INNER JOIN
ret_vwSalaried salaried ON calcs.[SalariedGuid] = salaried.[Guid] INNER JOIN
prs_workingPeriods workingPeriods ON workingPeriods.[Id] = command.[MainWorkingPeriodID]
WHERE
ISNULL(calcs.[MainCalculation],0) = 1 AND
ISNULL(command.[Deleted],0)=0 AND
(#Keyword = '' OR salaried.PersonnelNo = #Keyword OR salaried.FullName LIKE N'%' + #Keyword + '%' OR salaried.FullNameReversed LIKE N'%' + #Keyword + '%') AND
(ISNULL(#calculationCommandType, 0) = 0 OR command.[Type] = #calculationCommandType) AND
(ISNULL(#StartYear, 0) = 0 OR command.[MainYear] >= #StartYear) AND
(ISNULL(#StartWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] >= #StartWorkingPeriodId) AND
(ISNULL(#EndYear, 0) = 0 OR command.[MainYear] <= #EndYear) AND
(ISNULL(#EndWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] <= #EndWorkingPeriodId) AND
(ISNULL(#Status, -1) = -1 OR command.[Approved] = #Status) AND
(ISNULL(#SalariedType, -1) = -1 OR salaried.[SalariedType] = #SalariedType) AND
(ISNULL(#SalariedGuid,'00000000-0000-0000-0000-000000000000') = '00000000-0000-0000-0000-000000000000' OR calcs.[SalariedGuid] = #SalariedGuid) AND
(#OfficeNumber IS NULL OR salaried.[OfficeNumber] LIKE '%'+#OfficeNumber+'%') AND
(ISNULL(#SalariedResultSetId, -1) = -1 OR calcs.[SalariedGuid] IN (SELECT [SalariedGuid] FROM ret_SalariedResultSetItems WHERE SalariedResultSetID = #SalariedResultSetId)) AND
(calcs.[SalariedGuid] IN (SELECT * FROM #AccessibleSalariedGuids))
), TableForTotalCount AS (SELECT COUNT(*) As TotalCount FROM Result)
SELECT
(SELECT TOP 1 TotalCount FROM TableForTotalCount) AS TotalCount,
*
FROM Result
ORDER BY
[RowNumber]
OFFSET #OffsetRows ROWS
FETCH NEXT #PageSize ROWS ONLY
and another one supposed to return some Guids
ALTER PROCEDURE [dbo].[ret_PayrollCalculations_GetFilteredPersonnels]
(
#CalculationCommandType int,
#StartWorkingPeriodId int,
#StartYear int,
#EndWorkingPeriodId int,
#EndYear int,
#Status int,
#SalariedGuid uniqueidentifier,
#SalariedType int,
#OfficeNumber varchar(64),
#SalariedResultSetId int,
#Keyword nvarchar(2024),
#OperationalUnitIds [dbo].[ListOfID] READONLY
)
AS
DECLARE #AccessibleSalariedGuids [dbo].[ListOfGuid]
IF EXISTS (SELECT * FROM #OperationalUnitIDs)
BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT FeatureGuid FROM prs_OperationalUnitFeatures
WHERE
OperationalUnitID in (SELECT * FROM #OperationalUnitIDs) AND
FeatureFlag IN (2,4)
END
ELSE BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT [Guid] FROM ret_vwSalaried
END
SELECT
calcs.[Guid]
FROM
ret_PayrollCalculationCommands command INNER JOIN
ret_PayrollCalculations calcs ON calcs.[CalculationCommandGuid] = command.[Guid] INNER JOIN
ret_vwSalaried salaried ON calcs.[SalariedGuid] = salaried.[Guid]
WHERE
ISNULL(calcs.[MainCalculation],0) = 1 AND
ISNULL(command.[Deleted],0)=0 AND
(#Keyword = '' OR salaried.PersonnelNo = #Keyword OR salaried.FullName LIKE N'%' + #Keyword + '%' OR salaried.FullNameReversed LIKE N'%' + #Keyword + '%') AND
(ISNULL(#calculationCommandType, 0) = 0 OR command.[Type] = #calculationCommandType) AND
(ISNULL(#StartYear, 0) = 0 OR command.[MainYear] >= #StartYear) AND
(ISNULL(#StartWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] >= #StartWorkingPeriodId) AND
(ISNULL(#EndYear, 0) = 0 OR command.[MainYear] <= #EndYear) AND
(ISNULL(#EndWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] <= #EndWorkingPeriodId) AND
(ISNULL(#Status, -1) = -1 OR command.[Approved] = #Status) AND
(ISNULL(#SalariedType, -1) = -1 OR salaried.[SalariedType] = #SalariedType) AND
(ISNULL(#SalariedGuid,'00000000-0000-0000-0000-000000000000') = '00000000-0000-0000-0000-000000000000' OR calcs.[SalariedGuid] = #SalariedGuid) AND
(#OfficeNumber IS NULL OR salaried.[OfficeNumber] LIKE '%'+#OfficeNumber+'%') AND
(ISNULL(#SalariedResultSetId, -1) = -1 OR calcs.[SalariedGuid] IN (SELECT [SalariedGuid] FROM ret_SalariedResultSetItems WHERE SalariedResultSetID = #SalariedResultSetId)) AND
(calcs.[SalariedGuid] IN (SELECT * FROM #AccessibleSalariedGuids))
When a bug appears I have to fix the problem in both stored procedures, to avoid duplication I wanted Where clauses in a function and call the function in stored procedures,
But I don't know how?

This is how I would approach this:
If you're using Microsoft sql-server, you can make transact-sql code.
Convert your sql procedure into a string and make the Where clause a text variable that you declare elsewhere.
So it's creating a meta- procedure.
For eg.
DECLARE #whereClause LONGTEXT;
DECLARE #SQLString LONGTEXT;
SET #whereClause = 'i=1'
SET #SQLString = 'SELECT * FROM table WHERE' & #whereClause
sp_executesql SQLString

Related

SQL query with a loop and two IF

I have a sql request below.
in the table [ServicesConf] there are 2 rows: ID = 1, 2, but after executing sql query to table [ServicesLog] 3 rows are inserted.
How to make only 2 rows be inserted?
DECLARE #cnt int = 1
,#max int = (SELECT COUNT(*) FROM [ServicesConf]);
WHILE #cnt <= #max
BEGIN
DECLARE #DateTimeNow datetime = GETDATE()
DECLARE #DateTimeNowTimeHM varchar(5) = FORMAT(#DateTimeNow, 'HH:mm') --CONVERT(varchar(5), GETDATE(),108)
DECLARE #DateTimeNowTimeM varchar(2) = FORMAT(#DateTimeNow, 'mm')
DECLARE #DateTimeNow_WeekDay varchar = (SELECT DATEPART(WEEKDAY,#DateTimeNow))
DECLARE #DateTimeNow_WeekDay_Check int = (SELECT 1 FROM [ServicesConf] WHERE [SCHEDULE_DAY] LIKE '%' + #DateTimeNow_WeekDay + '%' AND [ID] = #cnt)
DECLARE #DateTimeNow_WeekHour_Check int = (SELECT 1 FROM [ServicesConf] WHERE [SCHEDULE_HOUR] = #DateTimeNowTimeHM AND [ID] = #cnt)
DECLARE #DateTimeNow_Repeat_Check int = (SELECT 1 FROM [ServicesConf] WHERE [REPEAT] LIKE '%' + #DateTimeNowTimeM + '%' AND [ID] = #cnt)
IF (#DateTimeNow_WeekDay_Check = 1
AND #DateTimeNow_Repeat_Check = 1)
BEGIN
INSERT INTO [ServicesLog] ()
SELECT *
FROM [ServicesConf]
WHERE [REPEAT] IS NOT NULL
END
IF (#DateTimeNow_WeekDay_Check = 1
AND #DateTimeNow_WeekHour_Check = 1)
BEGIN
INSERT INTO [ServicesLog] ()
SELECT *
FROM [ServicesConf]
WHERE [REPEAT] IS NULL
END
SET #cnt = #cnt + 1
END

How to pass where clause as a parameter to a stored procedure

I have a stored procedure for paging and searching and I have a parameter #Condition. I need to pass it to the SQL statement in my stored procedures, and in #Condition, I have pass the where clause that is
And p.BrandID=1 And s.Store_Name='xyz'
But I get an error
Msg 102, Level 15, State 1, Line 29
Incorrect syntax near 'p'.
CREATE PROCEDURE [dbo].[spGetProduct]
#DisplayLength int,
#DisplayStart int,
#SortCol int,
#SortDir nvarchar(10),
#Search nvarchar(255) = NULL,
#Condition nvarchar(500) = NULL
as
begin
Declare #FirstRec int, #LastRec int
Set #FirstRec = #DisplayStart;
Set #LastRec = #DisplayStart + #DisplayLength;
DECLARE #ExequteSql NVARCHAR(MAX)
SET #ExequteSql = N'
WITH CTE_Products AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY
CASE WHEN (#SortCol = 3 AND #SortDir = "asc")
THEN p.ProductID
END ASC,
CASE WHEN (#SortCol = 3 AND #SortDir = "desc")
THEN p.ProductID
END DESC,
CASE WHEN (#SortCol = 4 AND #SortDir = "asc")
THEN s.Store_Name
END ASC,
CASE WHEN (#SortCol = 4 AND #SortDir = "desc")
THEN s.Store_Name
END DESC) AS RowNum,
COUNT(*) over() as TotalCount,
p.*, s.Store_Name, ss.SubStore_Name
FROM
((MST_Product p
INNER JOIN
MST_Store s on s.Store_ID = p.BrandID)
INNER JOIN
MST_SubStore ss on ss.SubStore_ID = p.SubStore_ID)
WHERE
(#Search IS NULL
OR p.ProductID LIKE "% + #Search + %"
OR s.Store_Name LIKE "% + #Search + %"
OR ss.SubStore_Name LIKE "% + #Search + %"
OR p.StoreRefCode LIKE "% + #Search + %"
OR p.PName LIKE "% + #Search + %") ' + #Condition + '
)
Select *
from CTE_Products
where RowNum > #FirstRec and RowNum <= #LastRec'
EXEC SP_EXECUTESQL #ExequteSql ,N'#FirstRec INT, #LastRec INT, #Search nvarchar(255), #SortCol int, #SortDir nvarchar(10)' ,
#FirstRec = #FirstRec ,#LastRec = #LastRec, #Search=#Search, #SortCol=#SortCol, #SortDir=#SortDir
END
Error is because of double quotes, It is used for identifiers. For string literals need use single quotes
Made few more changes as well
DECLARE #FirstRec INT,
#LastRec INT
SET #FirstRec = #DisplayStart;
SET #LastRec = #DisplayStart + #DisplayLength;
SET #Search = '%' + #Search + '%'
DECLARE #ExequteSql NVARCHAR(MAX)
SET #ExequteSql = N'
With CTE_Products as
(
Select ROW_NUMBER() over (order by '+case #SortCol when 3 then 'p.ProductID ' when 4 then 's.Store_Name ' end +case when #SortDir = 'asc' then 'asc' else 'desc' end+')
as RowNum,
COUNT(*) over() as TotalCount,
p.*, s.Store_Name, ss.SubStore_Name
from
MST_Product p INNER JOIN MST_Store s on s.Store_ID = p.BrandID
INNER JOIN MST_SubStore ss on ss.SubStore_ID = p.SubStore_ID
where (#Search IS NULL
Or p.ProductID like #Search
Or s.Store_Name like #Search
Or ss.SubStore_Name like #Search
Or p.StoreRefCode like #Search
Or p.PName like #Search ) '
+ #Condition
+ '
)
Select *
from CTE_Products
where RowNum > #FirstRec and RowNum <= #LastRec'
print #ExequteSql
EXEC Sp_executesql
#ExequteSql,
N'#FirstRec INT, #LastRec INT, #Search nvarchar(255), #SortCol int, #SortDir nvarchar(10)',
#FirstRec = #FirstRec,
#LastRec = #LastRec,
#Search=#Search,
#SortCol=#SortCol,
#SortDir=#SortDir
To call the procedure
EXEC Spgetproduct
#DisplayLength = 1,
#DisplayStart = 1,
#SortCol = 3,
#SortDir ='asc',
#Search = 'ab',
#Condition = ' And p.BrandID=1 And s.Store_Name=''xyz''' -- here you need to double the single quotes

How to get parent Id from a run time generated row_number() as unique id in SQL

I have removed while loop used before but furnishing exact results. Now everything works fine except parentkey.
How to get "parentkey" in the stored procedure perfectly??
The procedure furnishes wrong results if more than 1 same parent is addded in same/different level of bom. The results shows one parent for all childs. It should show both parents separately with childs. The following part does not furnish exact result in case explained above.
(SELECT MAX(e.idcolumn) FROM #tExplode E WHERE e.fcomponent = b.fparent AND e.fcomprev = b.fparentrev AND e.cfacilityid = b.pfacilityid AND e.idcolumn > 0 ) As parentkey
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'M2M_Std_BOM_Explosion' AND type = 'P')
DROP PROCEDURE M2M_Std_BOM_Explosion
GO
CREATE Procedure [dbo].[M2M_Std_BOM_Explosion]
#pcPartNo CHAR(25),
#pcPartRev CHAR(3),
#pcFac CHAR(20),
#plIndent Bit
As
Begin
set nocount on
if object_id('tempdb..#tExplode') is not null drop table #tExplode
declare #sql as varchar(max) = ''
create table #tExplode
(
ID int not null,
lvl int not null,
CompPath varchar(8000),
ItmPath varchar(8000),
display varchar(100),
fcomponent varchar(25),
cfacilityid varchar(20),
fcomprev varchar(3),
fparent varchar(25),
fparentrev varchar(3),
pfacilityid varchar(20),
fitem varchar(6),
fqty numeric(15,5),
fsumqty numeric(15,5),
fst_ef_dt datetime,
fend_ef_dt datetime,
bomid int,
fnoperno int,
fltooling bit,
fbommemo varchar(8000),
fprodcl varchar(20),
flfssvc bit,
idcolumn Integer,
timestamp_column timestamp,
flextend bit,
fcompudrev varchar(3),
fcparudrev varchar(3),
forder int
)
Insert into #tExplode( ID,lvl,CompPath,ItmPath,display,fcomponent,cfacilityid,fcomprev,
fparent,fparentrev,pfacilityid,fitem,fqty,fsumqty,fst_ef_dt,
fend_ef_dt,bomid,fnoperno,fltooling,fbommemo,flfssvc,flextend,
fcompudrev,fcparudrev,forder,idcolumn)
SELECT 1,
0,
Cast(Rtrim(ltrim(#pcFac))+rtrim(ltrim(#pcPartNo))+rtrim(ltrim(#pcPartRev)) as varchar(8000)),
Cast(rtrim(ltrim(#pcFac))+rtrim(ltrim(#pcPartNo))+rtrim(ltrim(#pcPartRev)) as Varchar(8000)),
cast(1 AS varchar(100)),
#pcPartNo,
#pcFac,
#pcPartRev,
'',
'',
'',
'',
1,
1,
{d '1900-01-01'},
{d '1900-01-01'},
0,
'',
0,
'',
0,
0,
'',
'',
0,
0
FROM (SELECT #pcFac fac,
#pcPartNo fpartno,
#pcPartRev frev) x
LEFT JOIN inrtgc i On i.fac=x.fac And i.fpartno=x.fpartno And i.fcpartrev=x.frev
; WITH t AS (
select ID,lvl,CompPath,ItmPath,display,fcomponent,cfacilityid,fcomprev,
fparent,fparentrev,pfacilityid,fitem,fqty,fsumqty,fst_ef_dt,
fend_ef_dt,
bomid,
fnoperno,
fltooling,
fbommemo,
flfssvc,
flextend,
fcompudrev,
fcparudrev,
forder
from #tExplode
UNION ALL
SELECT b.identity_column,
t.lvl+1,
rtrim(ltrim(t.CompPath)) + '!' + rtrim(ltrim(b.pfacilityid)) + rtrim(ltrim(b.fcomponent)) + Replicate(' ',25-Len(rtrim(ltrim(b.fcomponent))))+ rtrim(ltrim(b.fcomprev + '!')),
rtrim(ltrim(t.ItmPath)) + '!' + rtrim(ltrim(b.fitem)),
Cast(replicate(' ',2*t.lvl) + b.fcomponent as Varchar(100)),
Cast(b.fcomponent as Varchar(25)),
Cast(b.cfacilityid as Varchar(20)),
Cast(b.fcomprev as Varchar(3)),
Cast(b.fparent as Varchar(25)),
Cast(b.fparentrev as Varchar(3)),
Cast(b.pfacilityid as Varchar(20)),
Cast(b.fitem as varchar(6)),
b.fqty,
Cast(CASE
WHEN b.flextend = 1 THEN b.fqty * ISNULL(t.fsumqty, cast(1 AS numeric(15,5)))
ELSE b.fqty
END as Numeric(15,5)),
b.fst_ef_dt,
b.fend_ef_dt,
b.identity_column,
ISNULL(b.fnoperno,cast(0 AS int)),
b.fltooling,
Cast(b.fbommemo as Varchar(8000)),
b.flfssvc,
b.flextend,
Cast(b.fcompudrev as Varchar(3)),
Cast(b.fcparudrev as Varchar(3)),
0
FROM inboms b
inner join t ON b.pFacilityID = t.cFacilityID
AND b.fparent = t.fcomponent
AND b.fparentrev = t.fcomprev
)
insert into #tExplode
(ID,lvl,CompPath,ItmPath,display,fcomponent,cfacilityid,fcomprev,
fparent,fparentrev,pfacilityid,fitem,fqty,fsumqty,fst_ef_dt,
fend_ef_dt,
bomid,
fnoperno,
fltooling,fbommemo,flfssvc,
flextend,
fcompudrev,fcparudrev,forder,idcolumn)
select ID,lvl,CompPath,ItmPath,display,fcomponent,cfacilityid,fcomprev,
fparent,fparentrev,pfacilityid,fitem,fqty,fsumqty,fst_ef_dt,
fend_ef_dt,
bomid,
fnoperno,
fltooling,fbommemo,
flfssvc,
flextend,
fcompudrev,fcparudrev,forder,row_number() over (order by lvl,comppath,cfacilityid,fcomponent,fcomprev,forder) from t
Set #sql = 'select b.idcolumn,b.lvl,
b.comppath,
b.itmpath,
b.display,
CASE WHEN m.fluseudrev = 1 THEN b.fcompudrev ELSE b.fcomprev END as disprev,
b.fitem,
fsource,
b.fqty,
CASE when b.flextend = 1 then b.fsumqty ELSE ((b.fqty * ISNULL(b.fsumqty, cast(1 AS numeric(15,5))))/Isnull(i.fSpq,1)) END as fsumqty,
fmeasure,
b.fnoperno,
CASE WHEN inbomm.fpartno IS NULL THEN SPACE(1) ELSE ''*'' END as isparent, --Working
b.fst_ef_dt,
b.fend_ef_dt,
b.bomid,
b.fcomponent,
b.cfacilityid,
b.fcomprev,
m.fdescript as fdesc,
b.fparent,
b.fparentrev,
b.pfacilityid,
ISNULL(m.identity_column, CAST(0 As Int)) as partid,
fidims,
Case When m.fcstscode=''O'' Then ''Obsolete''
Else
CASE WHEN NOT ((b.fst_ef_dt IS NULL) OR (b.fst_ef_dt={d ''1900-01-01''})) AND
DATEDIFF(day,b.fst_ef_dt, GetDate()) < 0
THEN ''Future''
WHEN NOT ((b.fend_ef_dt IS NULL) OR (b.fend_ef_dt={d ''1900-01-01''})) AND
DATEDIFF(day,b.fEnd_ef_dt, GETDATE()) > 0
THEN ''Expired''
ELSE ''Current''
END
End as effectivity,
b.fltooling,
b.fbommemo,
m.fprodcl,
fllotreqd,
b.flfssvc,
b.timestamp_column,
(SELECT MAX(e.idcolumn) FROM #tExplode E WHERE e.fcomponent = b.fparent AND e.fcomprev = b.fparentrev AND e.cfacilityid = b.pfacilityid AND e.idcolumn > 0 ) As parentkey,
b.flextend,
m.fluseudrev,
b.fcompudrev,
b.fcparudrev,
b.forder
from #tExplode b LEFT OUTER JOIN inmastx m ON
b.cFacilityID = m.fac AND
b.fcomponent = m.fpartno AND
b.fcomprev = m.frev
LEFT OUTER JOIN inbomm ON
b.pfacilityid = inbomm.facilityid AND
b.fComponent = InBomm.fPartno AND
b.fCompRev = InBomm.fcPartRev
LEFT OUTER JOIN inrtgc i ON
b.pfacilityid = i.fac AND
b.fComponent = i.fPartno AND
b.fCompRev = i.fcPartRev
where ' + case when #plIndent= 1 then 'b.lvl >= 1' else 'b.lvl = 1' end + '
order by ' + case when #plIndent= 1 then 'b.comppath,b.cfacilityid,b.fcomponent,b.fcomprev,b.forder' else 'b.comppath,b.forder' end + ''
Exec(#sql)
drop table #tExplode
end
--How to get "parentkey" in the stored procedure perfectly??
--The procedure furnishes wrong results if more than 1 same parent is addded in --same/different level of bom. The results shows one parent for all childs.

Append string in where clause in SQL

I have a function in SQL that returns where clause result like this
CREATE FUNCTION dwd.GetSearchCriteria
(
#pValue NVARCHAR(50),
#pCriteriaOption NVARCHAR(3)
)
RETURNS varchar(30)
AS
BEGIN
declare
#WHERE varchar(2000)
IF(#pValue IS NOT NULL)
BEGIN
SET #WHERE = CASE WHEN #pCriteriaOption = 'ST' THEN ' like ''' + #pValue + '%'''
WHEN #pCriteriaOption = 'ET' THEN ' like ''' + '%' + #pValue + ''''
WHEN #pCriteriaOption = 'CT' THEN ' like ' + '''%' + #pValue + '%'''
ELSE ''
END
END
ELSE
BEGIN
SET #WHERE = '= NULL';
END
RETURN #WHERE
END
I have a query that like this which calls this function
declare
#WHERE varchar(2000)
SET #WHERE=dwd.GetSearchCriteria ('A','ET')
SELECT FirstName FROM dwd.[User] WHERE FirstName + #WHERE
My function returns suppose { like %A% } . I need to append it to first name .
It returns this error
An expression of non-boolean type specified in a context where a
condition is expected, near '#WHERE'.
I have along SP like this
ALTER PROCEDURE [dwd].[ADMIN_USER_DETAIL]
(
#pApplicationClientID bigint,
#pUserID bigint,
/* Optional Filters for Dynamic Search*/
#pFirstName nvarchar(50) = NULL,
#pLastName nvarchar(50) = NULL,
#pEmail nvarchar(255) = NULL,
#pLocation nchar(10) = NULL,
#pPhoneNumber nvarchar(50) = NULL,
#pPseudoName nvarchar(500) = NULL,
/*– Pagination Parameters */
#pPageNo INT = 1,
#pPageSize INT = 10,
/*– Sorting Parameters */
#pSortColumn nvarchar(50) = 'FirstName',
#pSortOrder nvarchar(4)='ASC',
#pTotalCount int output
)
AS
BEGIN
/*–Declaring Local Variables corresponding to parameters for modification */
DECLARE
#lFirstName nvarchar(50),
#lLastName nvarchar(50),
#lEmail nvarchar(255),
#lLocation nchar(10),
#lPhoneNumber nvarchar(50),
#lPseudoName nvarchar(500),
#lPageNbr INT,
#lPageSize INT,
#lSortCol NVARCHAR(50),
#lFirstRec INT,
#lLastRec INT,
#lTotalRows INT,
#TotalCount INT
/*Setting Local Variables*/
SET #lFirstName = LTRIM(RTRIM(#pFirstName))
SET #lLastName = LTRIM(RTRIM(#pLastName))
SET #lEmail = LTRIM(RTRIM(#pEmail))
SET #lLocation = LTRIM(RTRIM(#pLocation))
SET #lPhoneNumber = LTRIM(RTRIM(#pPhoneNumber))
SET #lPseudoName = LTRIM(RTRIM(#pPseudoName))
SET #lPageNbr = #pPageNo
SET #lPageSize = #pPageSize
SET #lSortCol = LTRIM(RTRIM(#pSortColumn))
SET #lFirstRec = ( #lPageNbr - 1 ) * #lPageSize
SET #lLastRec = ( #lPageNbr * #lPageSize + 1 )
SET #lTotalRows = #lFirstRec - #lLastRec + 1
; WITH User_Results
AS (
SELECT ROW_NUMBER() OVER (ORDER BY
CASE WHEN (#lSortCol = 'FirstName' AND #pSortOrder='ASC')
THEN U1.FirstName
END ASC,
CASE WHEN (#lSortCol = 'FirstName' AND #pSortOrder='DESC')
THEN U1.FirstName
END DESC,
CASE WHEN (#lSortCol = 'LastName' AND #pSortOrder='ASC')
THEN U1.LastName
END ASC,
CASE WHEN #lSortCol = 'LastName' AND #pSortOrder='DESC'
THEN U1.LastName
END DESC,
CASE WHEN #lSortCol = 'Email' AND #pSortOrder='ASC'
THEN U1.Email
END ASC,
CASE WHEN #lSortCol = 'Email' AND #pSortOrder='DESC'
THEN U1.Email
END DESC,
CASE WHEN #lSortCol = 'Location' AND #pSortOrder='ASC'
THEN U1.LocationID
END ASC,
CASE WHEN #lSortCol = 'Location' AND #pSortOrder='DESC'
THEN U1.LocationID
END DESC,
CASE WHEN #lSortCol = 'PhoneNumber' AND #pSortOrder='ASC'
THEN U1.PhoneNumber
END ASC,
CASE WHEN #lSortCol = 'PhoneNumber' AND #pSortOrder='DESC'
THEN U1.PhoneNumber
END DESC,
CASE WHEN #lSortCol = 'PseudoName' AND #pSortOrder='ASC'
THEN U1.PseudoName
END ASC,
CASE WHEN #lSortCol = 'PseudoName' AND #pSortOrder='DESC'
THEN U1.PseudoName
END DESC
) AS ROWNUM,
Count(*) over () AS TotalCount,
U1.ID,
U1.FirstName,
U1.LastName,
U1.Email,
DPD.Value as Location,
U1.PhoneNumber,
U2.FirstName+' '+U2.LastName as ReportTo,
U1.PseudoName,
U1.IsActive,
US.ID AS SId,
US.SkillID AS SkillId,
UR.ID AS RId,
UR.RoleID AS RoleId,
U1.Created,
U1.Deleted
FROM dwd.[User] U1 with (nolock)
INNER JOIN dwd.[User] U2 with (nolock) ON U2.ID=U1.ReportTo
INNER JOIN dwd.[DomainParameterDetail] DPD with (nolock) ON DPD.ID=U1.LocationID
INNER JOIN dwd.[UserSkill] US WITH(NOLOCK) ON U1.ID = US.UserID
INNER JOIN dwd.[UserRole] UR WITH(NOLOCK) ON U1.ID = UR.UserID
WHERE
(#lFirstName IS NULL OR U1.FirstName = #lFirstName)
AND(#lLastName IS NULL OR U1.LastName LIKE '%' + #lLastName + '%')
AND(#lEmail IS NULL OR U1.Email LIKE '%' + #lEmail + '%')
AND (#lLocation IS NULL OR U1.LocationID LIKE '%' + #lLocation + '%')
AND (#lPhoneNumber IS NULL OR U1.PhoneNumber = #lPhoneNumber)
AND (#lPseudoName IS NULL OR U1.PseudoName LIKE '%' +#lPseudoName+ '%')
AND U1.IsActive=1 AND U1.Deleted=0 AND U1.ApplicationClientID=#pApplicationClientID
AND U1.ID<>1
)
SELECT
TotalCount,
ROWNUM,
ID,
FirstName,
LastName,
Email,
Location,
PhoneNumber,
ReportTo,
PseudoName,
IsActive,
S
Id,
SkillId,
RId,
RoleId,
Created,
Deleted
FROM User_Results AS USER_GET_RESULT
WHERE
ROWNUM > #lFirstRec
AND ROWNUM < #lLastRec
ORDER BY ROWNUM ASC
Select #TotalCount = Count(*) from dwd.[User]
WHERE IsActive=1 AND Deleted=0 AND ID<>1
Set #pTotalCount = #TotalCount
END
SO I have to get this donw in where clause of SP.
This is a bit long for a comment.
You can only do what you want using dynamic SQL. But, that seems entirely unnecessary, because all the comparisons use LIKE. So, it is better to write the function as:
CREATE FUNCTION dwd.GetSearchCriteria (
#pValue NVARCHAR(50),
#pCriteriaOption NVARCHAR(3)
)
RETURNS varchar(2000)
AS
BEGIN
declare #LIKEPATTERN varchar(2000) ;
SET #LIKEPATTERN = (CASE WHEN #PValue IS NULL THEN ''''''
WHEN #pCriteriaOption = 'ST' THEN '''' + #pValue + '%'''
WHEN #pCriteriaOption = 'ET' THEN '''' + '%' + #pValue + ''''
WHEN #pCriteriaOption = 'CT' THEN '''%' + #pValue + '%'''
ELSE ''''''
END)
RETURN #LIKEPATTERN
END ;
Note: Using an IF and CASE is redundant. The logic can be combined into a single expression. I also think return types should match the type of the variable being returned.
Then you can express the call as:
DECLARE #LIKEPATTERN varchar(2000);
SET #LIKEPATTERN = dwd.GetSearchCriteria('A','ET');
SELECT FirstName FROM dwd.[User] WHERE FirstName LIKE #LIKEPATTERN;

Improve case statement in order clause

I have the store sql
ALTER procedure [dbo].[TNNews_User_SearchBasic]
#Title nvarchar(400),
#CategoryId int,
#IsInterested int,
#IsHot int,
#IsTopCategory int,
#IsPublish int,
#PageSize int,
#PageIndex int,
#OrderBy varchar(20),
#PortalId int,
#LanguageId varchar(6)
as
DECLARE #EndTime DATETIME
DECLARE #StartTime DATETIME
SET #StartTime = GETDATE()
declare #tbCategory table(Id int)
DECLARE #StartRowIndex INT
IF #PageSize=0 SELECT #PageSize=count(*) FROM TNNews
IF(#PageIndex<0) SET #PageIndex=0
SET #StartRowIndex = #PageSize*(#PageIndex-1)+1
;WITH tmpCategory(Id, Name,ParentId,Level)
AS (
SELECT
e.Id,
e.Name,
e.ParentId,
1
FROM dbo.TNCategory AS e
WHERE
Id = #CategoryId or (#CategoryId='' and ParentId<=0)
UNION ALL
SELECT
e.Id,
e.Name,
e.ParentId,
Level + 1
FROM dbo.TNCategory AS e
JOIN tmpCategory AS d ON e.ParentId = d.Id
)
insert #tbCategory select Id from tmpCategory
;WITH tmpNews as
(
SELECT
a.Id,a.Title,a.Subject
,ROW_NUMBER() OVER (ORDER BY (Publisheddate) desc) as ThuTuBanGhi
FROM dbo.TNNews a
where 1 = 1
--and ( Title like '%'+#Title+'%')
and (#CategoryId = -1 or exists (select 0 from #tbCategory b where b.Id = a.CategoryId))
and (#IsInterested = -1 or IsIntrested = #IsInterested )
and (#IsHot = -1 or IsHot = #IsHot )
and (#IsTopCategory = -1 or IsTopCategory = #IsTopCategory )
and (#IsPublish = -1 or IsPublished = #IsPublish)
and PortalId=#PortalId
and LanguageId = #LanguageId
)
select *, (select COUNT(Id) from tmpNews) as 'TongSoBanGhi' from tmpNews
WHERE
ThuTuBanGhi BETWEEN (#StartRowIndex) AND (#StartRowIndex + #PageSize-1)
SET #EndTime = GETDATE()
PRINT 'StartTime = ' + CONVERT(VARCHAR(30),#StartTime,121)
PRINT ' EndTime = ' + CONVERT(VARCHAR(30),#EndTime,121)
PRINT ' Duration = ' + STR(DATEDIFF(MILLISECOND,#StartTime,#EndTime)) + ' millisecond'
select STR(DATEDIFF(MILLISECOND,#StartTime,#EndTime))
After this store excute
EXEC [dbo].[TNNews_User_SearchBasic]
#Title='',
#CategoryId = '',
#IsInterested = -1,
#IsHot = -1,
#IsTopCategory = -1,
#IsPublish = -1,
#PageSize = 20,
#PageIndex = 1,
#OrderBy = '',
#PortalId = 0,
#LanguageId = N'vi-VN'
go
The time excute about "200ms". And I create a new store "TNNews_User_SearchBasic1" with some change.
.....
--,ROW_NUMBER() OVER (ORDER BY (Publisheddate) desc) as ThuTuBanGhi
,ROW_NUMBER() OVER (ORDER BY (case when #OrderBy='VIEW_COUNT' then ViewCount else PublishedDate end) desc) as ThuTuBanGhi
.....
and now the time excute this store
EXEC [dbo].[TNNews_User_SearchBasic1]
#Title='',
#CategoryId = '',
#IsInterested = -1,
#IsHot = -1,
#IsTopCategory = -1,
#IsPublish = -1,
#PageSize = 20,
#PageIndex = 1,
#OrderBy = '',
#PortalId = 0,
#LanguageId = N'vi-VN'
GO
about 900ms.
I don't understand why there is a change. Please help me improve these stores.
PS: I put example db at: http://anhquan22.tk/Portals/0/Videos/web.rar
Finished analysis the structure of your database. The part of the problem is hiding in the table structure.
I have prepared a backup for you. In it, I slightly modified scheme to improve performance and some normalize the table. You can download it from this link.
...to your question, I would do like this -
DECLARE #SQL NVARCHAR(1000)
SELECT #SQL = N'
;WITH tmpCategory (Id, Name, ParentId, [Level]) AS
(
SELECT
e.Id
, e.Name
, e.ParentId
, 1
FROM dbo.TNCategory e
WHERE Id = #CategoryId OR (#CategoryId = '''' AND ParentId <= 0)
UNION ALL
SELECT
e.Id
, e.Name
, e.ParentId
, [Level] + 1
FROM dbo.TNCategory e
JOIN tmpCategory d ON e.ParentId = d.Id
)
SELECT
a.Id
, ROW_NUMBER() OVER (ORDER BY ' +
CASE WHEN #OrderBy = 'VIEW_COUNT'
THEN 'ViewCount'
ELSE 'PublishedDate'
END +' DESC) AS ThuTuBanGhi
FROM dbo.TNNewsMain a
where PortalId = #PortalId
AND LanguageId = #LanguageId'
+ CASE WHEN #IsInterested != -1 THEN ' AND IsInterested = #IsInterested' ELSE '' END
+ CASE WHEN #IsHot != -1 THEN ' AND IsHot = #IsHot' ELSE '' END
+ CASE WHEN #IsTopCategory != -1 THEN ' AND IsTopCategory = #IsTopCategory' ELSE '' END
+ CASE WHEN #IsPublish != -1 THEN ' AND IsPublish = #IsPublish' ELSE '' END
+ CASE WHEN #CategoryId != -1 THEN '' ELSE ' AND EXISTS(SELECT 1 FROM tmpCategory b WHERE b.Id = a.CategoryId)' END
INSERT INTO #temp (Id, ThuTuBanGhi)
EXECUTE sp_executesql
#SQL
, N'#PortalId INT
, #LanguageId VARCHAR(6)
, #CategoryId INT
, #IsInterested INT
, #IsHot INT
, #IsTopCategory INT
, #IsPublish INT'
, #PortalId = #PortalId
, #LanguageId = #LanguageId
, #CategoryId = #CategoryId
, #IsInterested = #IsInterested
, #IsHot = #IsHot
, #IsTopCategory = #IsTopCategory
, #IsPublish = #IsPublish;
SELECT
d.Id
, tm.Title
, tm.[Subject]
, d.ThuTuBanGhi
, c.TongSoBanGhi
FROM (
SELECT t.Id
, t.ThuTuBanGhi
FROM #temp t
WHERE t.ThuTuBanGhi BETWEEN #StartRowIndex AND #StartRowIndex + #PageSize - 1
) d
JOIN TNNewsMain tm ON d.Id = tm.Id
CROSS JOIN (
SELECT TongSoBanGhi = (SELECT COUNT(1) FROM #temp)
) c