Предположим, я использую базу данных Northwind и хочу выполнить запрос с помощью хранимой процедуры, которая содержит, помимо прочих параметров, следующее:
@Offset
, чтобы указать, где начинается нумерация страниц,
@Limit
для указания размера страницы,
@SortColumn
для указания столбца, используемого для сортировки,
@SortDirection
, чтобы указать сортировку по возрастанию или по убыванию.
Идея состоит в том, чтобы сделать нумерацию страниц в базе данных, поскольку результирующий набор содержит тысячи строк, поэтому кэширование не является опцией (а использование VIEWSTATE даже не рассматривается как, IMO, отстой).
Как вы, возможно, знаете, SQL Server 2005 предоставляет функцию ROW_NUMBER , которая возвращает порядковый номер строки в разделе набора результатов, начиная с 1 для первой строки в каждом разделе .
Нам нужна сортировка по каждому возвращаемому столбцу (пять в этом примере), и динамический 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
Я пробовал запрос несколько раз, с разными аргументами, и его производительность на самом деле довольно хорошая, но он все равно выглядит так, как будто его можно оптимизировать другим способом.
Что-то не так с этим запросом, или вы бы сделали это так? Вы предлагаете другой подход?