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
さまざまな引数を使用してクエリを数回試しましたが、そのパフォーマンスは実際には非常に優れていますが、他の方法で最適化されているように見えます。
このクエリに何か問題がありますか、それともこのようにしますか? 別のアプローチを提案しますか?