SQL Server 2005でROW_NUMBER()OVER()を使用して異なる列で並べ替えを使用したページ分割クエリ
-
04-07-2019 - |
質問
Northwindデータベースを使用しており、他のパラメーターの中でも特に以下を含むストアドプロシージャを介してクエリを実行するとします。
-
@Offset
でページ区切りの開始位置を示します -
@Limit
でページサイズを示します -
@SortColumn
は、ソートに使用される列を示します。 -
@SortDirection
、上位または下位のソートを示します。
結果セットには数千の行が含まれているため、データベースでページネーションを実行するという考え方です。したがって、キャッシングはオプションではありません(VIEWSTATEの使用はIMOであるとは見なされません)。
ご存知かもしれませんが、SQL Server 2005は ROW_NUMBER という機能を提供します。 結果セットのパーティション内の行の連続番号を返します。各パーティションの最初の行の1から始まります。
返されるすべての列でソートする必要があり(この例では5つ)、動的SQLはオプションではないため、2つの可能性があります: 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
異なる引数を使用してクエリを数回試行しましたが、そのパフォーマンスは実際には非常に良好ですが、それでも他の方法で最適化されているようです。
このクエリに問題はありますか、それともこのようにしますか?別のアプローチを提案しますか?
解決
シンプル:
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)でソートされます。逆も同様です。
同じORDER BY式でROW_NUMBER()関数が機能するようにします。
所属していません StackOverflow