您如何按参数订购?


16

只是想知道我是否可以对正在运行的存储过程征求一些反馈,以及是否存在一种处理场景的更有效方法(我敢肯定会存在!)。

基本上,我有一个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

--ELSE IF用于其他列排序

Answers:


16

可以使用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

您可能需要重新考虑“或”条件,因为它们可能会产生不良计划。我阅读过的关于此(以及替代方法)的最佳文章之一是T-SQL中的动态搜索条件

编辑:再次查看您的参数列表,主要过滤器似乎是@CustomerId和@UserId。我建议创建两个proc spJobs_SelectByCustomerId和spJobs_SelectByUserId,它们按各自的参数进行过滤,因此可以消除“ @Param = 0或Column = @Param”的条件。我想下一个重要的参数是@ShowCompleted(假定一旦完成一项工作,除非@ ShowCompleted = 1,否则它不会显示),我会考虑将其包括在CustomerId和UserId的索引中。

Edit2:有趣的是,这些问题有时会在您的脑海中浮现!:)在索引@ShowCompleted时,这是首先使用低选择性BIT列成为最佳策略的情况之一。还应考虑过滤索引


!直奔我的头,但是我不怕阅读和学习!感谢Mark抽空回答。潜意识如何继续处理这些事情确实很有趣。我也发现啤酒和尼古丁有帮助:)
VaticNZ 2011年

如果有任何需要澄清的地方,请随时提出您的问题或发表新文章。
Mark Storey-Smith'7

1
谢谢马克。我已经实现了你的一些建议,一切都只是一个奇怪的问题好...我已经张贴在另一个线程:dba.stackexchange.com/questions/4162/...
VaticNZ

不好,我没有解释您必须在单独的case表达式中处理不同的类型。已为您的新问题添加了答案。
Mark Storey-Smith,

此解决方案(CASE基于-)是否也会产生不良的执行计划?不会CASE针对每一行进行评估吗?
AndreiRînea2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.