Come ordini un parametro?


16

Mi chiedo solo se potrei chiedere un feedback su una procedura memorizzata che sto eseguendo e se esiste un modo più efficiente di gestire lo scenario (sono abbastanza sicuro che ci sarà!).

Fondamentalmente ho un singolo SP che chiamo per restituire un elenco di record (Lavori) che possono avere uno o più stati e un ordinamento (sto usando RowNum per il paging). Al momento sto usando WITH RECOMPILE perché le variazioni degli stati possono cambiare continuamente (a seconda dell'utente ecc.). C'è anche qualche filtro in corso.

Sto usando un'istruzione IF per eseguire essenzialmente lo stesso bit di codice con l'unica modifica è l'ordinamento.

Immagino che le mie domande siano: esiste un modo migliore per farlo (forse SP diversi per stati diversi)? Sto complicando troppo le cose a causa della mancanza di conoscenza (molto probabilmente) L'SP è effettivamente ok, ma richiede piccole modifiche per ridurre il numero di linee?

Ho incollato una parte del SP di seguito: l'unica differenza rispetto al codice completo sono le istruzioni IF aggiuntive per i diversi ordinamenti ...

Gradirei qualsiasi feedback.

Grazie in anticipo!

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 per l'ordinamento di altre colonne

Risposte:


16

L'ordinamento può essere curato con un'espressione CASE, qualcosa sulla falsariga di:

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

Potresti voler riconsiderare gli OR dove le condizioni possono generare piani scadenti. Uno dei migliori articoli che ho letto su questo (e gli approcci alternativi) sono le condizioni di ricerca dinamica in T-SQL

Modifica: guardando nuovamente l'elenco dei parametri, i filtri principali sembrano essere @CustomerId e @UserId. Suggerirei di creare due proc, spJobs_SelectByCustomerId e spJobs_SelectByUserId, che filtrano in base ai rispettivi parametri in modo da eliminare le condizioni "@Param = 0 o Column = @Param". Immagino che il prossimo parametro importante sia @ShowCompleted (presumendo che una volta che un lavoro è 'fatto', non viene mostrato a meno che @ ShowCompleted = 1), che prenderei in considerazione includendo negli indici su CustomerId e UserId.

Edit2: Divertente come queste domande a volte spuntino nella parte posteriore della tua mente! :) Nell'indicizzazione di @ShowCompleted, questa è una delle occasioni in cui l' utilizzo di una colonna BIT a bassa selettività può essere la migliore strategia . Dovrebbero essere considerati anche gli indici filtrati .


Wooosh! Tutto dritto sopra la mia testa, ma non ho paura di leggere e imparare! Grazie Marco per il tempo dedicato a rispondere. È davvero divertente come il subconcio continui a lavorare su queste cose. Trovo che anche la birra e la nicotina aiutino :)
VaticNZ,

Se hai bisogno di chiarimenti, sentiti libero di estendere la tua domanda o di iniziare un nuovo post.
Mark Storey-Smith,

1
Grazie Marco. Ho implementato alcuni dei tuoi suggerimenti e tutto va bene tranne uno strano problema ... Ho pubblicato un altro thread: dba.stackexchange.com/questions/4162/…
VaticNZ

Mio male, non ho spiegato che devi affrontare diversi tipi in espressioni di casi separati. Ho aggiunto una risposta alla tua nuova domanda.
Mark Storey-Smith,

questa soluzione ( CASEbasata su) non genererà anche un piano di esecuzione scadente? Non CASEverrà valutato per ogni riga?
Andrei Rînea,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.