Vat*_*cNZ 16 sql-server-2008 stored-procedures
只是想知道我是否可以就我正在运行的存储过程征求一些反馈,以及是否有更有效的方法来处理这种情况(我很确定会有!)。
基本上,我有一个 SP,我调用它来返回可能具有一个或多个状态和排序顺序的记录(作业)列表(我使用 RowNum 进行分页)。目前我正在使用 WITH RECOMPILE,因为状态的变化可能一直在变化(取决于用户等)。还有一些过滤正在进行。
我正在使用 IF 语句来运行相同的代码,唯一的变化是排序顺序。
我想我的问题是:有没有更好的方法来做到这一点(对于不同的状态可能有不同的 SP)?由于缺乏知识,我是否使事情变得过于复杂(很可能) SP 实际上还可以,但需要进行细微调整以减少行数?
我在下面粘贴了 SP 的一部分 - 与完整代码的唯一区别是不同排序顺序的附加 IF 语句......
我很感激任何反馈。
提前致谢!
PROCEDURE [dbo].[sp_Jobs]
@PageNumber int,
@PageSize int,
@FilterExpression varchar(500),
@OrderBy varchar(50),
@CustomerID int,
@ShowNotSet bit,
@ShowPlaced bit,
@ShowProofed bit,
@ShowReProofed bit,
@ShowApproved bit,
@ShowOnTime bit,
@ShowLate bit,
@ShowProblem bit,
@ShowCompleted bit,
@ShowDispatched bit,
@ShowUnapproved bit,
@ShowClosed bit,
@ShowReturned bit,
@UserID int
WITH RECOMPILE
AS
--JobNumber DESC
if @OrderBy='JobNumberDESC'
BEGIN
WITH Keys AS (SELECT TOP (@PageNumber * @PageSize) ROW_NUMBER() OVER (ORDER BY JobNumber DESC) as rn,P1.jobNumber,P1.CustID,P1.DateIn,P1.DateDue,P1.DateOut,p1.client,p1.MasterJobStatusID,p1.MasterJobStatusTimestamp,p1.OwnerID
FROM
vw_Jobs_List P1 WITH (NOLOCK)
WHERE
(@CustomerID = 0 OR CustID = @CustomerID)
AND (@UserID = 0 OR OwnerID = @UserID)
AND ((@ShowNotSet = 1 AND MasterJobStatusID=1) OR (@ShowPlaced = 1 AND MasterJobStatusID=2) OR (@ShowProofed = 1 AND MasterJobStatusID=3) OR (@ShowReProofed = 1 AND MasterJobStatusID=4) OR (@ShowApproved = 1 AND MasterJobStatusID=5) OR (@ShowOnTime = 1 AND MasterJobStatusID=6) OR (@ShowLate = 1 AND MasterJobStatusID=7) OR (@ShowProblem = 1 AND MasterJobStatusID=8) OR (@ShowCompleted = 1 AND MasterJobStatusID=9) OR (@ShowDispatched = 1 AND MasterJobStatusID=10) OR (@ShowUnapproved = 1 AND MasterJobStatusID=11) OR (@ShowClosed = 1 AND MasterJobStatusID=12) OR (@ShowReturned = 1 AND MasterJobStatusID=13)) AND (Search LIKE '%'+@FilterExpression+'%')
ORDER BY
P1.JobNumber DESC ),SelectedKeys AS (
SELECT TOP (@PageSize)SK.rn,SK.JobNumber,SK.CustID,SK.DateIn,SK.DateDue,SK.DateOut
FROM
Keys SK
WHERE
SK.rn > ((@PageNumber-1) * @PageSize)
ORDER BY
SK.JobNumber DESC)
SELECT SK.rn,J.JobNumber,J.OwnerID,J.Description,J.Client,SK.CustID,OrderNumber, CAST(DateAdd(d, -2, CAST(isnull(SK.DateIn,0) AS DateTime)) AS nvarchar) AS DateIn, CAST(DateAdd(d, -2, CAST(isnull(SK.DateDue,0) AS DateTime)) AS nvarchar) AS DateDue,CAST(DateAdd(d, -2, CAST(isnull(SK.DateOut,0) AS DateTime)) AS nvarchar) AS DateOut, Del_Method,Ticket#, InvoiceEmailed, InvoicePrinted, InvoiceExported, InvoiceComplete, JobStatus,j.MasterJobStatusID,j.MasterJobStatusTimestamp,js.MasterJobStatus
FROM SelectedKeys SK JOIN vw_Jobs_List J WITH (NOLOCK) ON j.JobNumber=SK.JobNumber JOIN tbl_SYSTEM_MasterJobStatus js WITH (NOLOCK) ON j.MasterJobStatusID=js.MasterJobStatusID
ORDER BY
SK.JobNumber DESC
END
Run Code Online (Sandbox Code Playgroud)
--ELSE IF 用于其他列排序
Mar*_*ith 17
排序可以使用 CASE 表达式来处理,类似于:
ORDER BY
CASE WHEN @SortDirection = 'A' THEN
CASE
WHEN @SortBy = 'JobNumber' THEN JobNumber
WHEN @SortBy = 'JobId' THEN JobId
END
END ASC
, CASE WHEN @SortDirection = 'D' THEN
CASE
WHEN @SortBy = 'JobNumber' THEN JobNumber
WHEN @SortBy = 'JobId' THEN JobId
END
END DESC
Run Code Online (Sandbox Code Playgroud)
您可能需要重新考虑 OR'd where 条件,因为它们可能会产生糟糕的计划。我读过的最好的文章之一是T-SQL 中的动态搜索条件
编辑:再次查看您的参数列表,主要过滤器似乎是@CustomerId 和@UserId。我建议创建两个过程,spJobs_SelectByCustomerId 和 spJobs_SelectByUserId,它们按各自的参数进行过滤,以便消除“@Param = 0 或 Column = @Param”条件。我猜下一个重要参数是@ShowCompleted(假设一旦工作“完成”,除非@ShowCompleted=1,否则不会显示),我会考虑将其包含在CustomerId 和UserId 的索引中。
Edit2:有趣的是,这些问题有时会在你的脑海中打勾!:) 在索引 @ShowCompleted 时,这是首先使用低选择性 BIT 列可以成为最佳策略的场合之一。还应考虑过滤索引。