Предполагая, что столбец проиндексирован, следующее должно быть достаточно эффективным.
С двумя поисками по 10 строк, а затем сортировка (до) 20 вернулась.
WITH CTE
AS ((SELECT TOP 10 *
FROM YourTable
WHERE YourCol > 32
ORDER BY YourCol ASC)
UNION ALL
(SELECT TOP 10 *
FROM YourTable
WHERE YourCol <= 32
ORDER BY YourCol DESC))
SELECT TOP 10 *
FROM CTE
ORDER BY ABS(YourCol - 32) ASC
(т.е. потенциально что-то вроде ниже)
Или другая возможность (которая уменьшает количество строк, отсортированных до 10)
WITH A
AS (SELECT TOP 10 *,
YourCol - 32 AS Diff
FROM YourTable
WHERE YourCol > 32
ORDER BY Diff ASC, YourCol ASC),
B
AS (SELECT TOP 10 *,
32 - YourCol AS Diff
FROM YourTable
WHERE YourCol <= 32
ORDER BY YourCol DESC),
AB
AS (SELECT *
FROM A
UNION ALL
SELECT *
FROM B)
SELECT TOP 10 *
FROM AB
ORDER BY Diff ASC
NB: План выполнения выше был для простого определения таблицы
CREATE TABLE [dbo].[YourTable](
[YourCol] [int] NOT NULL CONSTRAINT [SomeIndex] PRIMARY KEY CLUSTERED
)
Технически сортировка в нижней ветви также не требуется, так как это тоже заказано Diff, и было бы возможно объединить два упорядоченных результата. Но я не смог получить этот план.
Запрос имеет ORDER BY Diff ASC, YourCol ASC
и не только ORDER BY YourCol ASC
, потому что это было то, что в итоге работало, чтобы избавиться от сортировки в верхней ветви плана. Мне нужно было добавить вторичный столбец (хотя он никогда не изменит результат, так как YourCol
он будет одинаковым для всех значений с одинаковым значением Diff), чтобы он проходил объединение слиянием (объединение) без добавления сортировки.
Похоже, что SQL Server может сделать вывод, что индекс X, найденный в порядке возрастания, будет доставлять строки, упорядоченные по X + Y, и сортировка не требуется. Но он не в состоянии сделать вывод, что перемещение индекса в порядке убывания приведет к появлению строк в том же порядке, что и YX (или даже просто унарный минус X). Обе ветви плана используют индекс, чтобы избежать сортировки, но TOP 10
затем сортируются в нижней ветви Diff
(даже если они уже в этом порядке), чтобы получить их в нужном порядке для слияния.
Для других запросов / определений таблиц может быть сложнее или невозможно получить план слияния всего лишь с одной ветвью - так как он основан на поиске упорядочивающего выражения, что SQL Server:
- Признает, что поиск по индексу предоставит указанный порядок, поэтому сортировка перед вершиной не требуется .
- Рад использовать в операции слияния, поэтому не требует сортировки после
TOP
SELECT TOP 10 * FROM YourTable ORDER BY ABS(YourCol - 32) ;
еще более простой. Также не эффективен.