2010-10-07 29 views
12

Viết một thủ tục lưu trữ trong MS SQL Server 2008 R2, tôi muốn tránh sử dụng DSQL ...Conditional SQL ORDER BY ASC/DESC cho cột alpha

Tôi muốn các cách sắp xếp (ASC hoặc DESC) là có điều kiện.

Bây giờ, với một cột số tôi chỉ đơn giản sẽ sử dụng một tuyên bố vụ án và phủ nhận giá trị bắt chước ASC hoặc DESC ... Đó là:

... ORDER BY CASE @OrderAscOrDesc WHEN 0 THEN [NumericColumn] ELSE -[NumericColumn] END ASC 

một phương pháp thích hợp để làm điều này với một là gì cột alpha? EDIT: Tôi nghĩ một cách thông minh nhưng nó có vẻ không hiệu quả khủng khiếp ... Tôi có thể chèn cột alpha đã ra lệnh của tôi vào một bảng tạm thời với một autonumber sau đó sắp xếp theo autonumber bằng cách sử dụng phương pháp mô tả ở trên.

EDIT2:

Các bạn nghĩ gì về phương pháp này?

ORDER BY CASE @OrderAscOrDesc WHEN 0 THEN [AlphaColumn] ELSE '' END ASC, 
CASE @OrderAscOrDesc WHEN 0 THEN '' ELSE [AlphaColumn] END DESC 

Tôi không biết nếu buộc một sắp xếp trên một cột thống nhất là hiệu quả hơn bắt nguồn từ số chuỗi được sắp xếp dù

Trả lời

27

Một lựa chọn

;WITH cQuery AS 
(
    SELECT 
     *, 
     ROW_NUMBER() OVER (ORDER BY SortColumn) AS RowNum 
    FROM 
     MyTable 
) 
SELECT 
    * 
FROM 
    cQuery 
ORDER BY 
    RowNum * @Direction --1 = ASC or -1 = DESC 

Hoặc TRƯỜNG HỢP mà IMHO là một chút uglier

ORDER BY 
    CASE WHEN 'ASC' THEN SortColumn ELSE '' END ASC, 
    CASE WHEN 'DESC' THEN SortColumn ELSE '' END DESC 
+0

thông minh, khá giống với giải pháp của tôi, tôi đăng trong chỉnh sửa. Tôi hy vọng điều gì đó hiệu quả hơn là lấy một bản sao được sắp xếp khác của dữ liệu chỉ để tạo ra thứ tự sắp xếp số .... – Matthew

+0

@Matthew PK: bạn phải thay thế chuỗi cho một số phù hợp hoặc thêm các loại giả cho không các trường hợp liên quan. Không có gì * thực sự * thông minh Tôi sợ – gbn

+0

Bạn nghĩ gì về cách tiếp cận "hai mệnh đề ORDER BY" trong bản chỉnh sửa thứ hai của tôi? – Matthew

1

Đây là một trong những trường hợp khi các giải pháp cụ thể có thể thích hợp hơn rable to generic, đặc biệt khi chúng ta xử lý một lượng lớn dữ liệu. Tôi sẽ:

IF @OrderAscOrDesc = 0 THEN BEGIN 
    SELECT ... 
    FROM ... 
    ORDER BY [AlphaColumn] ASC 
END ELSE BEGIN 
    SELECT ... 
    FROM ... 
    ORDER BY [AlphaColumn] DESC 
END 

Nếu bạn có một chỉ mục trên [AlphaColumn], bạn có thể thỉnh thoảng có được một kế hoạch tốt hơn với một truy vấn cụ thể hơn, so với một chung một cỡ vừa cho tất cả một.

Edit: để tạo điều kiện tái sử dụng mã, bạn có thể quấn chọn của bạn trong một UDF inline - nó sẽ thực hiện chỉ cũng như:

IF @OrderAscOrDesc = 0 THEN BEGIN 
    SELECT ... 
    FROM YourInlineUdf(...) 
    ORDER BY [AlphaColumn] ASC 
END ELSE BEGIN 
    SELECT ... 
    FROM YourInlineUdf(...) 
    ORDER BY [AlphaColumn] DESC 
END 
+0

Tôi đồng ý với nguyên tắc bạn ' đã đặt ra. Trong ứng dụng cụ thể của tôi, tôi không muốn làm điều này vì truy vấn tương đối dài và sử dụng một số phép nối. Mối quan tâm của tôi sẽ là mã trùng lặp 6 lần hoặc lâu hơn khiến việc bảo trì và cập nhật trong tương lai trở nên khó khăn. – Matthew

+0

@Matthew PK: để tạo điều kiện sử dụng lại mã, bạn có thể bọc lựa chọn của bạn trong UDF nội tuyến - nó sẽ hoạt động tốt –