2008-10-23 23 views
7

假設我使用的是Northwind數據庫,並且希望通過包含其他參數的存儲過程運行查詢,以下:使用SQL Server 2005中的ROW_NUMBER()OVER()對不同列進行排序的分頁查詢

  • @Offset指示分頁開始的地方,
  • @Limit指示頁面大小,
  • @SortColumn指示用於排序的目的列,
  • @SortDirection,表示上升或下降的排序。

這個想法是做數據庫的分頁,因爲結果集包含數以千計的行,所以緩存不是一個選項(並且使用VIEWSTATE甚至不被視爲IMO)。

正如你可能知道SQL Server 2005提供的功能ROW_NUMBER返回結果集的分區內的行的順序號,從1開始的每個分區的第一行。

我們需要對每個返回的列進行排序(本例中爲5個),並且動態SQL不是一個選項,所以我們有兩種可能性:使用大量的IF ... ELSE ...並有10個查詢,這是一個地獄要維護的,查詢如下所示:

WITH PaginatedOrders AS (
    SELECT 
     CASE (@SortColumn + ':' + @SortDirection) 
      WHEN 'OrderID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID ASC) 
      WHEN 'OrderID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID DESC) 
      WHEN 'CustomerID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.CustomerID ASC) 
      WHEN 'CustomerID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.CustomerID DESC) 
      WHEN 'EmployeeID:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.EmployeeID ASC) 
      WHEN 'EmployeeID:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.EmployeeID DESC) 
      WHEN 'OrderDate:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderDate ASC) 
      WHEN 'OrderDate:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderDate DESC) 
      WHEN 'ShippedDate:A' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID ASC) 
      WHEN 'ShippedDate:D' THEN ROW_NUMBER() OVER (ORDER BY Orders.OrderID DESC) 
     END AS RowNumber, 
     OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate 
    FROM Orders 
    -- WHERE clause goes here 
) 
SELECT 
    RowNumber, OrderID, CustomerID, EmployeeID, OrderDate, ShippedDate, 
    @Offset, @Limit, @SortColumn, @SortDirection 
FROM PaginatedOrders 
WHERE RowNumber BETWEEN @Offset AND (@Offset + @Limit - 1) 
ORDER BY RowNumber 

我試着查詢了幾次,使用不同的參數,它的表現是相當不錯的實際,但它劇照看起來像它可能被優化的一些其他的方式。

這個查詢有什麼問題,或者你會這樣做嗎?你提出一個不同的方法?

+0

我的愚蠢的錯誤,修正了。請再試一次。 – Tomalak 2008-10-27 14:28:18

回答

6

簡單:

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 

如果選擇ASC順序,或者反之亦然這將排序NULL(DESC)。

讓ROW_NUMBER()函數在相同的ORDER BY表達式上工作。

+0

今天下午我會試着用查詢計劃器和分析器的這個功能,只是爲了比較結果:) – 2008-10-27 12:20:46

相關問題