Якщо припустити, що стовпчик індексується, наступне повинно бути досить ефективно.
З двома прагненнями 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) ;
ще простіші. Не ефективний також.