Consulta paginada usando classificação em colunas diferentes usando ROW_NUMBER () OVER () no SQL Server 2005

Vamos supor que estou usando o banco de dados Northwind e gostaria de executar uma consulta por meio de um procedimento armazenado que contenha, entre outros parâmetros, o seguinte:

@Offset para indicar onde a paginação começa,@Limit para indicar o tamanho da página,@SortColumn para indicar a coluna usada para fins de classificação,@SortDirection, para indicar a classificação ascendente ou descendente.

A idéia é fazer a paginação no banco de dados, pois o conjunto de resultados contém milhares de linhas, portanto o armazenamento em cache não é uma opção (e usar VIEWSTATE nem sequer é considerado IMO, é uma porcaria).

Como você deve saber, o SQL Server 2005 fornece a funçãoROW_NUMBER qualretorna o número seqüencial de uma linha dentro de uma partição de um conjunto de resultados, iniciando em 1 para a primeira linha em cada partição.

Precisamos classificar todas as colunas retornadas (cinco neste exemplo) e o SQL dinâmico não é uma opção; portanto, temos duas possibilidades: usar muitasIF ... ELSE ... e ter 10 consultas, o que é um inferno para manter, ou ter uma consulta como a seguinte:

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

Eu tentei a consulta várias vezes, com argumentos diferentes, e seu desempenho é bastante bom, na verdade, mas parece que pode ser otimizado de outra maneira.

Há algo de errado com esta consulta ou você faria dessa maneira? Você propõe uma abordagem diferente?

questionAnswers(1)

yourAnswerToTheQuestion