คุณสั่งซื้อพารามิเตอร์อย่างไร


16

เพียงแค่สงสัยว่าฉันสามารถขอความคิดเห็นเกี่ยวกับขั้นตอนการจัดเก็บที่ฉันใช้อยู่หรือไม่และมีวิธีการจัดการสถานการณ์ที่มีประสิทธิภาพมากขึ้นหรือไม่ (ฉันค่อนข้างแน่ใจว่าจะมี!)

โดยทั่วไปฉันมี SP เดียวที่ฉันเรียกเพื่อส่งกลับรายการของเรกคอร์ด (งาน) ที่อาจมีสถานะอย่างน้อยหนึ่งสถานะและเรียงลำดับ (ฉันใช้ RowNum สำหรับการเพจ) ในขณะที่ฉันกำลังใช้กับ RECOMPILE เพราะความหลากหลายของสถานะสามารถเปลี่ยนแปลงได้ตลอดเวลา (ขึ้นอยู่กับผู้ใช้ ฯลฯ ) นอกจากนี้ยังมีการกรองเกิดขึ้น

ฉันใช้คำสั่ง IF เพื่อเรียกใช้บิตของรหัสเดียวกันโดยมีการเปลี่ยนแปลงเพียงอย่างเดียวคือการเรียงลำดับ

ฉันเดาว่าคำถามของฉันคือ: มีวิธีที่ดีกว่าในการทำสิ่งนี้ (อาจเป็น SP ที่แตกต่างกันสำหรับสถานะที่แตกต่างกัน)? ฉันเข้าใจเรื่องนี้มากเกินไปเนื่องจากขาดความรู้ (น่าจะเป็น) SP จริงหรือไม่ แต่ต้องการปรับแต่งเล็กน้อยเพื่อลดจำนวนบรรทัด

ฉันได้วางส่วนหนึ่งของ SP ด้านล่าง - ความแตกต่างเพียงอย่างเดียวกับรหัสเต็มคือคำสั่ง IF เพิ่มเติมสำหรับการเรียงลำดับที่แตกต่างกัน ...

ฉันขอขอบคุณข้อเสนอแนะใด ๆ

ขอบคุณล่วงหน้า!

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 สำหรับการเรียงลำดับคอลัมน์อื่น ๆ

คำตอบ:


16

การเรียงลำดับสามารถได้รับการดูแลด้วยนิพจน์กรณี, บางสิ่งบางอย่างตามสายของ:

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

คุณอาจต้องการพิจารณา OR ในกรณีที่เงื่อนไขตามที่พวกเขามีแนวโน้มที่จะสร้างแผนไม่ดี หนึ่งในบทความที่ดีที่สุดที่ฉันได้อ่านครอบคลุมเรื่องนี้ (และแนวทางอื่น) คือเงื่อนไขการค้นหาแบบไดนามิกใน T-SQL

แก้ไข: ดูรายการพารามิเตอร์ของคุณอีกครั้งตัวกรองหลักจะปรากฏเป็น @CustomerId และ @UserId ฉันขอแนะนำให้สร้างสอง procs, spJobs_SelectByCustomerId และ spJobs_SelectByUserId ซึ่งกรองตามพารามิเตอร์ที่เกี่ยวข้องดังนั้นคุณจึงกำจัดเงื่อนไข '@Param = 0 หรือ Column = @Param' ฉันคิดว่าพารามิเตอร์ที่สำคัญต่อไปคือ @ShowCompleted (สมมติว่าเมื่องาน 'เสร็จสิ้น' จะไม่แสดงเว้นแต่ @ ShowCompleted = 1) ซึ่งฉันจะพิจารณารวมไว้ในดัชนีของ CustomerId และ UserId

แก้ไข 2: เรื่องตลกที่บางครั้งคำถามเหล่านี้จั๊กจี้อยู่ในใจของคุณ! :) ในการจัดทำดัชนี @ShowCompleted นี้เป็นหนึ่งในครั้งที่ใช้ต่ำหัวกะทิ BIT คอลัมน์แรกที่สามารถกลยุทธ์ที่ดีที่สุด ดัชนีที่กรองควรพิจารณาด้วย


Wooosh! ตรงไปทั่วหัวของฉัน แต่ฉันไม่กลัวที่จะอ่านและเรียนรู้! ขอบคุณ Mark ที่สละเวลาตอบคำถาม เป็นเรื่องตลกจริง ๆ ว่าจิตใต้สำนึกยังทำงานผ่านสิ่งเหล่านี้อย่างไร ฉันพบว่าเบียร์และนิโคตินช่วยด้วย :)
VaticNZ

หากมีสิ่งใดที่ต้องการคำชี้แจงอย่าลังเลที่จะขยายคำถามของคุณหรือเริ่มโพสต์ใหม่
Mark Storey-Smith

1
ขอบคุณมาร์ค ฉันได้ดำเนินการตามคำแนะนำของคุณแล้วและทุกอย่างก็ดียกเว้นปัญหาแปลก ๆ ... ฉันโพสต์ในหัวข้ออื่น: dba.stackexchange.com/questions/4162/…
VaticNZ

ฉันไม่ดีไม่ได้อธิบายว่าคุณต้องจัดการกับประเภทที่แตกต่างกันในการแสดงออกกรณีแยก ได้เพิ่มคำตอบสำหรับคำถามใหม่ของคุณแล้ว
Mark Storey-Smith

โซลูชันนี้ ( CASE- ตาม) จะไม่สร้างแผนการดำเนินการที่ไม่ดีด้วยหรือไม่ สิ่งนี้จะไม่CASEถูกประเมินสำหรับแต่ละแถวหรือไม่
Andrei Rînea
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.