2008-10-23 12 views
7

Giả sử tôi đang sử dụng cơ sở dữ liệu Northwind và tôi muốn chạy truy vấn thông qua một thủ tục được lưu trữ có chứa, trong số các tham số khác, sau:Truy vấn được phân trang bằng cách sắp xếp trên các cột khác nhau bằng ROW_NUMBER() OVER() trong SQL Server 2005

  • @Offset để chỉ ra nơi pagination bắt đầu,
  • @Limit để chỉ ra kích thước trang,
  • @SortColumn để chỉ ra cột được sử dụng cho các mục đích phân loại,
  • @SortDirection, để chỉ ra tăng dần hoặc phân loại hậu duệ.

Ý tưởng là thực hiện phân trang trên cơ sở dữ liệu, vì tập kết quả chứa hàng nghìn hàng nên bộ nhớ đệm không phải là tùy chọn (và sử dụng VIEWSTATE thậm chí không được coi là IMO, sucks).

Như bạn đã biết SQL Server 2005 cung cấp các chức năng ROW_NUMBERtrả về số tuần tự của một hàng trong một phân vùng của một tập kết quả, bắt đầu từ 1 cho dòng đầu tiên trong mỗi phân vùng.

Chúng tôi cần phân loại trên mỗi cột được trả lại (năm trong ví dụ này) và SQL động không phải là một tùy chọn, vì vậy chúng tôi có hai khả năng: sử dụng nhiều IF ... ELSE ... và có 10 truy vấn, đó là địa ngục để duy trì hoặc truy vấn như sau:

Tôi đã thử truy vấn nhiều lần, với các đối số khác nhau và hiệu suất của nó khá tốt, nhưng vẫn có vẻ như nó có thể được tối ưu hóa theo một cách khác.

Có vấn đề gì với truy vấn này hay bạn sẽ làm theo cách này? Bạn có đề xuất một cách tiếp cận khác không?

+0

Lỗi ngu ngốc của tôi, đã khắc phục điều đó. Vui lòng thử lại. – Tomalak

Trả lời

6

đơn giản:

SELECT 
    OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate, 
    @Offset, @Limit, @SortColumn, @SortDirection 
FROM 
    Orders 
WHERE 
    ROW_NUMBER() OVER 
    (
    ORDER BY 
     /* same expression as in the ORDER BY of the whole query */ 
) BETWEEN (@PageNum - 1) * @PageSize + 1 AND @PageNum * @PageSize 
    /* AND more conditions ... */ 
ORDER BY 
    CASE WHEN @SortDirection = 'A' THEN 
    CASE @SortColumn 
     WHEN 'OrderID' THEN OrderID 
     WHEN 'CustomerID' THEN CustomerID 
     /* more... */ 
    END 
    END, 
    CASE WHEN @SortDirection = 'D' THEN 
    CASE @SortColumn 
     WHEN 'OrderID' THEN OrderID 
     WHEN 'CustomerID' THEN CustomerID 
     /* more... */ 
    END 
    END DESC 

này sẽ sắp xếp về NULL (DESC) nếu trật tự ASC được chọn, hoặc ngược lại.

Để hàm ROW_NUMBER() hoạt động trên cùng một biểu thức ORDER BY.

+0

Chiều nay, tôi sẽ thử với chức năng này với trình hoạch định truy vấn và hồ sơ, chỉ để so sánh kết quả :) –

+0

Tôi háo hức muốn xem kết quả. :-) – Tomalak

+0

Chính xác lỗi này cung cấp lỗi sau: 'Msg 207, Cấp 16, Tiểu bang 1, Dòng 41 - Tên cột không hợp lệ 'RowNumber'.'. Tôi sẽ sử dụng mệnh đề WITH sau đó. –