2010-11-11 27 views
22

Cú pháp MS SQL đúng để chọn nhiều cột ORDER BY khi ORDER BY dựa trên câu lệnh CASE là gì?Thứ tự động bằng lệnh SELECT với nhiều cột

dưới đây hoạt động tốt với các cột duy nhất, nhưng tôi cần phải sắp xếp theo nhiều cột:

SELECT * FROM Products 
ORDER BY 
CASE WHEN @SortIndex = 1 THEN Price END ASC, 
CASE WHEN @SortIndex = 2 THEN Price DESC, Title ASC END <-- problem line 

Trả lời

39

Bạn có thể thử này

SELECT * FROM Products 
ORDER BY 
CASE WHEN @SortIndex = 1 THEN Price END ASC, 
CASE WHEN @SortIndex = 2 THEN Price END DESC, 
CASE WHEN @SortIndex = 2 THEN Title END ASC 
+0

Đối với vấn đề cụ thể của tôi, tôi sử dụng 'ASC END THEN -Giá, 'thay vì' THEN Giá END DESC' như chúng tôi đã có để tải các loại các cột từ cùng một cột trong DB. Vì vậy, để làm cho nó sạch sẽ, chúng tôi tách từng cột bằng một khoảng trắng và sử dụng dấu âm như là một thay thế cho 'DESC' – th3byrdm4n

1

Làm điều này ... và nói lời tạm biệt với hiệu suất của bạn . Thật không may là giải pháp tốt nhất là sử dụng sql động.

+0

Chăm sóc để xây dựng? Ứng dụng thực sự của tôi về điều này cho một thủ tục lưu trữ khá phức tạp, nơi SQL động là không thể. – BradB

+0

+1. xem câu trả lời của tôi dưới đây – Sadhir

+5

Theo kinh nghiệm của tôi (chỉ 12 năm làm việc với MSSQL), tôi đã chạy vào nhiều thứ tám, nơi những cấu trúc này tạo ra các kế hoạch khủng khiếp. Nó không phải là đó là xấu cho mỗi, chỉ là tôi thấy nó không đáng tin cậy, tức là. truy vấn hoạt động tốt ngày hôm nay có thể tạo ra các kế hoạch không hoạt động trong 4 tháng tới) –

2

Hãy thử điều này dưới dạng tác động thấp hơn đến hiệu suất máy chủ - giả sử bạn chỉ có 2 giá trị tại @SortIndex (1 và 2). Nếu không, hãy mở rộng Nếu có nhiều điều kiện hơn.

If @SortIndex = 1 
BEGIN 
    SELECT * FROM Products ORDER BY Price ASC 
END 
ELSE 
BEGIN 
    SELECT * FROM Products ORDER BY Price DESC, TITLE ASC 
END 
+0

Tôi ngửi các thông số ở đây :) .. Giải pháp này thực sự có thể giới thiệu tham số sniffing – Sadhir

+1

Giả sử rằng đây là một thủ tục lưu sẵn và @SortIndex là tham số cho sproc. Và vì lý do, hãy nói rằng có một điều kiện khác - nếu @SortIndex = 3, sau đó sắp xếp theo chỉ Tile và cho phép nói có một chỉ mục về giá và một chỉ số trên tiêu đề. Bây giờ, nếu bạn gọi sproc lần đầu tiên với @SortIndex = 1, máy chủ SQL sẽ tạo một kế hoạch thực hiện sử dụng chỉ mục về giá. Khi bạn gọi lại sproc, bất kể giá trị của @SortTitle, máy chủ SQL sẽ sử dụng cùng một gói như trước. Vì vậy, nếu @SortTitle = 3, nó vẫn sẽ sử dụng chỉ mục về giá mặc dù nó là vô dụng ở đây – Sadhir

+0

Tôi không bao giờ giả định đây là một thủ tục được lưu trữ. Nếu nó là một câu lệnh SQL đơn giản với khai báo biến và các giá trị phân bổ cho các biến, thì truy vấn sẽ có một kế hoạch thực thi tốt, tùy thuộc vào lá "IF" nào nó sẽ đi.Người dùng không nói rằng đó là một thủ tục được lưu trữ với một tham số; và nếu nó thực sự là - tham số sniffing có thể được kích hoạt hoặc vô hiệu hóa xem xét số lượng hàng lấy ra cho mỗi kết hợp. – yrushka

6

@Brad. Pavel đã đề xuất những điều sau (tôi nghĩ),

DECLARE @query VARCHAR(MAX) 

SET @query = 'SELECT * FROM Products 
       ORDER BY 
       ' 

IF (@SortIndex = 1) 
    SET @query [email protected] + ' Price ASC ' 
ELSE IF (@SortIndex = 2) 
    SET @query [email protected] + ' Price DESC, Title ASC ' 

sp_executesql @query 

Tại sao bạn nghĩ rằng sql động không phù hợp với các thủ tục được lưu trữ phức tạp? Đó là chính xác những nơi mà bạn nên sử dụng SQL động vì nó có thể giúp giảm sự phức tạp và giải quyết các vấn đề như tham số sniffing. Tôi đồng ý rằng sql năng động có nhược điểm của nó, nhưng tôi sẽ khuyên bạn nên ít nhất là cho nó một thử nếu nó làm việc cho bạn.

+0

Cảm ơn bạn đã đề xuất. Tôi sẽ thử phương pháp này. – BradB

+1

Truy vấn phức tạp hơn (đặc biệt là các thủ tục danh sách đáng sợ) với nhiều đầu vào, nhiều lựa chọn sắp xếp, vv, kết quả đáng tin cậy hơn bạn nhận được từ SQL động. –

+0

Đề xuất duy nhất của tôi ở đây là bảo vệ các truy vấn động của bạn khỏi các cuộc tấn công tiêm. – Keith

1

Bạn có thể viết lại này:

ORDER BY 
CASE WHEN @SortIndex = 1 THEN Price END ASC, 
CASE WHEN @SortIndex = 2 THEN Price DESC, Title ASC END 

như

CASE WHEN @SortIndex = 1 THEN Price END ASC, 
CASE WHEN @SortIndex = 2 THEN Price DESC END, 
Title ASC 

này thêm cột sắp xếp thêm cho TẤT CẢ các trường hợp nhưng trong hoàn cảnh của tôi, đó là những gì tôi muốn.

Bạn cũng có thể làm được điều này (chỉ là ví dụ):

CASE WHEN @SortIndex = 1 THEN Price END ASC,Title ASC, 
CASE WHEN @SortIndex = 2 THEN Price DESC END 
+0

Kịch bản này hoạt động tốt cho những gì tôi cần. Cảm ơn! – tmorell

+0

Tôi đã bỏ phiếu cho câu trả lời của yrushka. Đây là một lựa chọn hợp lệ ở đây. Nhưng trong trường hợp của tôi, nơi tôi đã sử dụng ở trên, người dùng đã có 12 columbs có thể sắp xếp theo phong cách/tùy chọn này có vẻ thực tế hơn. –

+0

Và nhận xét trên của tôi sẽ có ý nghĩa hơn nếu tôi thêm rằng bản thân câu lệnh truy vấn khá liên quan. Nó sẽ là không thực tế trong trường hợp đó để lặp lại toàn bộ stating 12 lần với mệnh đề orderby khác nhau. –

Các vấn đề liên quan