パラメーターをどのように並べ替えますか?


16

実行中のストアドプロシージャに関するフィードバックを求めることができるかどうか、およびシナリオを処理するより効率的な方法があるかどうか疑問に思うだけです(きっとあるはずです!)。

基本的に、1つ以上のステータスと並べ替え順序を持つ可能性のあるレコード(ジョブ)のリストを返すために呼び出す単一の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

回答:


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

貧弱なプランを生成する可能性が高いため、OR条件を再検討することができます。これ(および代替アプローチ)をカバーするために読んだ最高の記事の1つは、T-SQLの動的検索条件です。

編集:パラメーターリストをもう一度見ると、プライマリフィルターは@CustomerIdと@UserIdのように見えます。2つのプロシージャspJobs_SelectByCustomerIdとspJobs_SelectByUserIdを作成することをお勧めします。これらのパラメータは、それぞれのパラメータでフィルタリングするため、「@ Param = 0またはColumn = @Param」条件を排除します。次の重要なパラメーターは@ShowCompleted(ジョブが「完了」すると、@ ShowCompleted = 1でない限り表示されないと仮定)です。これは、CustomerIdとUserIdのインデックスに含めることを検討します。

編集2:これらの質問があなたの心の奥で時々カチカチと鳴るのは面白い!:) @ShowCompletedのインデックス作成では、これは、低選択性BIT列を最初使用することが最良の戦略になる可能性がある場合の1つです。フィルター選択されたインデックスも考慮する必要があります。


うわー!まっすぐ頭の上で、しかし、私は読書と学習を恐れていません!返信に時間を割いてくれてありがとう。副意識がこれらのことをどのように続けているかは実に面白いです。ビールとニコチンも役立つと思います:)
VaticNZ

何か説明が必要な場合は、質問を拡張するか、新しい投稿を開始してください。
マークストーリースミス

1
ありがとうマーク。私はあなたの提案の一部を実装しましたし、すべてが奇妙な問題を除いて良いです...私は別のスレッドに投稿した:dba.stackexchange.com/questions/4162/...
VaticNZ

私の悪いことは、別々のcase式で異なる型を扱う必要があることを説明しませんでした。新しい質問への回答を追加しました。
マークストーリースミス

このソリューション(- CASEベース)は、実行計画も貧弱ではありませんか?これはCASE行ごとに評価されませんか?
アンドレイリネア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.