Wie ordnet man nach einem Parameter?

16

Ich frage mich nur, ob ich Feedback zu einer von mir ausgeführten gespeicherten Prozedur einholen kann und ob das Szenario effizienter gehandhabt werden kann (ich bin mir ziemlich sicher, dass dies der Fall sein wird!).

Grundsätzlich habe ich einen einzelnen SP, den ich aufrufe, um eine Liste von Datensätzen (Jobs) mit einem oder mehreren Status und einer Sortierreihenfolge zurückzugeben (ich verwende RowNum zum Blättern). Im Moment benutze ich WITH RECOMPILE, da sich die Variationen der Status ständig ändern können (abhängig vom Benutzer usw.). Es wird auch gefiltert.

Ich verwende eine IF-Anweisung, um im Wesentlichen das gleiche Codebit auszuführen, wobei die einzige Änderung die Sortierreihenfolge ist.

Ich denke, meine Fragen sind: Gibt es eine bessere Möglichkeit, dies zu tun (möglicherweise unterschiedliche SPs für unterschiedliche Status)? Bin ich aufgrund mangelnder Kenntnisse überkompliziert? (Sehr wahrscheinlich) Ist der SP tatsächlich in Ordnung, erfordert jedoch geringfügige Änderungen, um die Anzahl der Zeilen zu verringern?

Ich habe unten einen Teil der SP eingefügt - der einzige Unterschied zum vollständigen Code sind die zusätzlichen IF-Anweisungen für die verschiedenen Sortierreihenfolgen ...

Ich würde mich über Feedback freuen.

Danke im Voraus!

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 für die Sortierung anderer Spalten

VaticNZ
quelle

Antworten:

16

Die Sortierung kann mit einem CASE-Ausdruck erledigt werden, der etwa wie folgt aussieht:

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

Möglicherweise möchten Sie den OP-Bereich überprüfen, wenn die Bedingungen schlecht sind. Einer der besten Artikel, die ich über dieses Thema (und die alternativen Ansätze) gelesen habe, ist dynamische Suchbedingungen in T-SQL

Bearbeiten: Wenn Sie Ihre Parameterliste erneut betrachten, werden die primären Filter als @CustomerId und @UserId angezeigt. Ich würde vorschlagen, zwei Procs zu erstellen, spJobs_SelectByCustomerId und spJobs_SelectByUserId, die nach ihren jeweiligen Parametern filtern, sodass Sie die Bedingungen '@Param = 0 oder Column = @Param' eliminieren. Ich denke, der nächste wichtige Parameter ist @ShowCompleted (vorausgesetzt, dass ein einmal erledigter Job nur angezeigt wird, wenn @ ShowCompleted = 1), was ich in den Indizes für die Kunden-ID und die Benutzer-ID berücksichtigen würde.

Edit2: Komisch, wie diese Fragen manchmal im Hinterkopf auftauchen! :) Bei der Indizierung von @ShowCompleted ist dies eine der Situationen, in denen die Verwendung einer BIT-Spalte mit niedriger Selektivität die beste Strategie sein kann . Auch gefilterte Indizes sollten berücksichtigt werden.

Mark Storey-Smith
quelle
Wooosh! Alles direkt über meinem Kopf, aber ich habe keine Angst vor Lesen und Lernen! Vielen Dank, dass Sie sich die Zeit genommen haben, um zu antworten. Es ist in der Tat lustig, wie das Unterbewusstsein diese Dinge weiter durcharbeitet. Ich finde Bier und Nikotin helfen auch :)
VaticNZ
Wenn etwas geklärt werden muss, können Sie Ihre Frage gerne erweitern oder einen neuen Beitrag verfassen.
Mark Storey-Smith
1
Danke Markus. Ich habe einige Ihrer Vorschläge umgesetzt und alles ist gut, bis auf ein seltsames Problem ... Ich habe auf einem anderen Thread gepostet: dba.stackexchange.com/questions/4162/…
VaticNZ
Meine schlechte, hat nicht erklärt, dass Sie mit verschiedenen Typen in verschiedenen Ausdrücken umgehen müssen. Haben Sie eine Antwort auf Ihre neue Frage hinzugefügt.
Mark Storey-Smith
CASEErzeugt diese ( -basierte) Lösung nicht auch einen schlechten Ausführungsplan? Wird dies CASEnicht für jede Zeile ausgewertet?
Andrei Rînea