Bir parametreyi nasıl SİPARİŞ EDİNİZ?


16

Sadece çalıştığım bir saklı yordam hakkında bazı geri bildirim talep edip edemeyeceğini ve senaryoyu işlemenin daha etkili bir yolu olup olmadığını merak ediyorum (olacağından eminim!).

Temelde bir veya daha fazla durum ve bir sıralama düzeni (disk belleği için RowNum kullanıyorum) olabilir kayıtları (İşler) listesini döndürmek için çağırmak tek bir SP var. Şu anda durumlarla ilgili değişiklikler (kullanıcı vb. Bağlı olarak) her zaman değişebilir çünkü RECOMPILE ile kullanıyorum. Ayrıca bazı filtreleme devam ediyor.

Temelde sadece sıralama düzeni olan tek değişiklik kod aynı bitini çalıştırmak için bir IF deyimi kullanıyorum.

Sorularım sanırım: Bunu yapmanın daha iyi bir yolu var mı (belki farklı durumlar için farklı SP'ler)? Bilgi eksikliğinden dolayı aşırı karmaşıklaşıyor muyum (büyük olasılıkla) SP aslında iyi mi, ancak satır sayısını azaltmak için küçük ayarlamalar gerektiriyor mu?

Aşağıdaki SP bir kısmını yapıştırdım - tam kod tek fark farklı sıralama siparişleri için ek IF ifadeler ...

Herhangi bir geri bildirim için teşekkür ederiz.

Şimdiden teşekkürler!

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

--Diğer sütun sıralaması için EĞER

Yanıtlar:


16

Sıralama bir CASE ifadesi ile halledilebilir:

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

Koşulların kötü planlar oluşturma olasılığı yüksek olan OR'leri yeniden gözden geçirmek isteyebilirsiniz. Bunu (ve alternatif yaklaşımları) kapsayan okuduğum en iyi makalelerden biri T-SQL'deki Dinamik Arama Koşulları

Düzenleme: Parametre listenize tekrar baktığınızda, birincil filtreler @CustomerId ve @UserId olarak görünür. Ben '@Param = 0 veya Column = @Param' koşullarını ortadan kaldırmak için ilgili parametreleri ile filtre spJobs_SelectByCustomerId ve spJobs_SelectByUserId, iki procs oluşturmayı öneriyorum. Ben bir sonraki önemli param @ ShowSpleted (bir iş 'tamamlandığında' varsayalım, ben @ ShowCompleted = 1 sürece sürece gösterilmiyor), ı CustomerId ve UserId dizinleri dahil dikkate alacağını sanırım.

Edit2: Komik bu sorular bazen zihninizin arkasında kene nasıl! :) @ShowCompleted dizinlemesinde bu, Düşük Seçiciliğe Sahip bir BIT Sütunu Kullanmanın Önce En İyi Strateji Olabileceği durumlardan biridir . Filtrelenmiş dizinler de dikkate alınmalıdır.


Wooosh! Tamamen kafamın üstünde, ama okumaktan ve öğrenmekten korkmuyorum! Cevap vermek için zaman ayırdığınız için teşekkürler Mark. Bilinçaltının bu şeyler üzerinde nasıl çalışmaya devam ettiği gerçekten komik. Ben de bira ve nikotin yardım bul :)
VaticNZ

Herhangi bir şeyin açıklığa ihtiyacı varsa, sorunuzu uzatmaktan veya yeni bir gönderi başlatmaktan çekinmeyin.
Mark Storey-Smith

1
Teşekkürler Mark. Bazı önerilerinizi uyguladım ve garip bir sorun dışında her şey iyi ... Başka bir iş parçacığında yayınladım: dba.stackexchange.com/questions/4162/…
VaticNZ

Benim hatam, ayrı vaka ifadelerinde farklı türlerle uğraşmanız gerektiğini açıklamamıştı. Yeni sorunuza bir cevap eklediniz.
Mark Storey-Smith

Bu çözüm ( CASEtabanlı) kötü bir yürütme planı oluşturmayacak mı? Bu CASE, her satır için değerlendirilmeyecek mi?
Andrei Rînea
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.