Я понимаю, что это распространенная проблема и ранее обсуждалась на SO , но я подумал, что снова подниму этот вопрос в надежде, что какая-то жизнеспособная альтернатива может быть найдено.
Возьмите следующий SQL, который объединяет пейджинг с динамическим порядком:
WITH CTE AS (
SELECT
OrderID,
ROW_NUMBER() OVER (ORDER BY
CASE WHEN @SortCol='OrderID' THEN OrderID END ASC,
CASE WHEN @SortCol='CustomerName' THEN Surname END ASC
) AS ROW_ID
FROM Orders WHERE X
)
SELECT Orders.* FROM CTE
INNER JOIN Orders ON CTE.OrderID = Orders.OrderID
WHERE ROW_ID BETWEEN @RowStart AND @RowStart + @RowCount -1;
Как известно, метод ROW_NUMBER() плохо работает на больших таблицах, поскольку индексы таблицы не могут быть правильно использованы при использовании нескольких операторов CASE в предложении ORDER BY (см. ссылка).
Решение, которое мы использовали в течение ряда лет, - это построить строку, которая затем выполняется с помощью sp_executesql. Производительность хороша при использовании динамического SQL, подобного этому, но полученный код ужасен с точки зрения удобочитаемости.
Я слышал о методе ROWCOUNT, но насколько я знаю, он все еще подвержен тем же проблемам, когда вы вводите динамический порядок по элементу.
Итак, рискуя спросить невозможное, какие существуют другие варианты?
ИЗМЕНИТЬ
Чтобы сделать некоторый полезный прогресс, я собрал три запроса, в которых были освещены различные предлагаемые методы:
-
Текущее, динамическое решение SQL (время выполнения 147 мс)
-
gbn Решение (время выполнения 1687 мс)
-
Решение Anders (время выполнения 1604 мс)
-
Решение Мухмуда (время выполнения 46 мс)