Bagaimana Anda MEMESAN DENGAN parameter?

16

Hanya ingin tahu apakah saya dapat meminta umpan balik tentang prosedur tersimpan yang saya jalankan dan apakah ada cara yang lebih efisien untuk menangani skenario (Saya cukup yakin akan ada!).

Pada dasarnya saya memiliki satu SP yang saya panggil untuk mengembalikan daftar catatan (Pekerjaan) yang mungkin memiliki satu status atau lebih dan semacam urutan (Saya menggunakan RowNum untuk paging). Saat ini saya menggunakan DENGAN RECOMPILE karena variasi pada status dapat berubah sepanjang waktu (tergantung pada pengguna dll). Ada juga beberapa penyaringan yang terjadi.

Saya menggunakan pernyataan IF untuk dasarnya menjalankan sedikit kode yang sama dengan satu-satunya perubahan menjadi urutan sortir.

Saya kira pertanyaan saya adalah: Apakah ada cara yang lebih baik untuk melakukan ini (mungkin SP berbeda untuk status yang berbeda)? Apakah saya terlalu rumit hal-hal karena kurangnya pengetahuan (sangat mungkin) Apakah SP sebenarnya ok, tetapi memerlukan sedikit penyesuaian untuk mengurangi jumlah baris?

Saya telah menempelkan sebagian SP di bawah ini - satu-satunya perbedaan pada kode lengkap adalah pernyataan IF tambahan untuk berbagai jenis pesanan ...

Saya menghargai umpan balik apa pun.

Terima kasih sebelumnya!

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 JIKA untuk penyortiran kolom lainnya

VaticNZ
sumber

Jawaban:

16

Penyortiran dapat diatasi dengan ekspresi KASUS, sesuatu seperti:

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

Anda mungkin ingin mempertimbangkan kembali ATAU di mana kondisinya karena mereka cenderung menghasilkan rencana yang buruk. Salah satu artikel terbaik yang pernah saya baca yang membahas hal ini (dan pendekatan alternatif) adalah Kondisi Pencarian Dinamis dalam T-SQL

Sunting: Melihat lagi pada daftar parameter Anda, filter utama tampaknya @CustomerId dan @UserId. Saya menyarankan untuk membuat dua procs, spJobs_SelectByCustomerId dan spJobs_SelectByUserId, yang memfilter menurut parameternya masing-masing sehingga Anda menghilangkan kondisi '@Param = 0 atau Kolom = @Param'. Saya kira param penting berikutnya adalah @ShowCompleted (dengan anggapan bahwa sekali suatu pekerjaan sudah 'selesai', itu tidak akan ditampilkan kecuali @ ShowCompleted = 1), yang akan saya pertimbangkan termasuk dalam indeks pada CustomerId dan UserId.

Sunting2: Lucu bagaimana pertanyaan-pertanyaan ini terkadang muncul di benak Anda! :) Pada pengindeksan @ShowCompleted, ini adalah salah satu kesempatan di mana Menggunakan Kolom BIT Selektivitas-Rendah Pertama Dapat Menjadi Strategi Terbaik . Indeks yang difilter juga harus dipertimbangkan.

Mark Storey-Smith
sumber
Wooosh! Langsung di atas kepala saya, tetapi saya tidak takut membaca dan belajar! Terima kasih Mark telah meluangkan waktu untuk merespons. Sungguh lucu bagaimana subconcious terus bekerja melalui hal-hal ini. Saya menemukan bir dan nikotin juga membantu :)
VaticNZ
Jika ada yang perlu diklarifikasi, silakan lanjutkan pertanyaan Anda atau mulai posting baru.
Mark Storey-Smith
1
Mark terima kasih. Saya telah mengimplementasikan beberapa saran Anda dan semuanya baik-baik saja kecuali masalah aneh ... Saya telah memposting di utas lain: dba.stackexchange.com/questions/4162/…
VaticNZ
Buruk saya, tidak menjelaskan bahwa Anda harus berurusan dengan berbagai jenis dalam ekspresi kasus terpisah. Telah menambahkan jawaban untuk pertanyaan baru Anda.
Mark Storey-Smith
tidakkah solusi ini ( CASE-berbasis) menghasilkan rencana eksekusi yang buruk juga? Bukankah ini CASEakan dievaluasi untuk setiap baris?
Andrei Rînea