it-swarm.it

Come ordini un parametro?

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 può avere uno o più stati e un ordinamento (sto usando RowNum per il paging). 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) Il SP è effettivamente ok, ma richiede piccole modifiche per ridurre il numero di righe?

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 '%'[email protected]+'%')

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

16
VaticNZ

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) è 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 sare prima una colonna BIT a bassa selettività può essere la migliore strategia . Indici filtrati dovrebbero essere presi in considerazione.

16