Zakładając, że kolumna jest indeksowana, poniższe elementy powinny być dość wydajne.
Z dwoma próbami po 10 wierszy, a następnie w pewnym sensie (do) 20 zwróconych.
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
(tzn. potencjalnie coś takiego poniżej)
Lub inna możliwość (która zmniejsza liczbę rzędów posortowanych do maksymalnie 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
Uwaga: Powyższy plan wykonania dotyczył prostej definicji tabeli
CREATE TABLE [dbo].[YourTable](
[YourCol] [int] NOT NULL CONSTRAINT [SomeIndex] PRIMARY KEY CLUSTERED
)
Technicznie rzecz biorąc, Sortowanie na dolnej gałęzi również nie powinno być potrzebne, ponieważ to też jest uporządkowane przez Diff i byłoby możliwe scalenie dwóch uporządkowanych wyników. Ale nie byłem w stanie uzyskać tego planu.
Zapytanie ma ORDER BY Diff ASC, YourCol ASC
nie tylko ORDER BY YourCol ASC
dlatego, że to właśnie skończyło się na pozbyciu się sortowania w górnej gałęzi planu. Musiałem dodać kolumnę dodatkową (nawet jeśli nigdy nie zmieni to wyniku, ponieważ YourCol
będzie taki sam dla wszystkich wartości z tym samym różnicą), więc przejdzie przez połączenie scalające (konkatenację) bez dodawania sortowania.
Wydaje się, że SQL Server może wnioskować, że indeks X poszukiwany w porządku rosnącym dostarczy wiersze uporządkowane przez X + Y i żadne sortowanie nie jest konieczne. Ale nie jest w stanie wywnioskować, że przesunięcie indeksu w kolejności malejącej spowoduje dostarczenie wierszy w tej samej kolejności co YX (lub nawet tylko jednoargumentowy minus X). Obie gałęzie planu używają indeksu, aby uniknąć sortowania, ale TOP 10
dolna gałąź jest następnie sortowana według Diff
(nawet jeśli są już w tej kolejności), aby uzyskać je w żądanej kolejności scalania.
W przypadku innych zapytań / definicji tabel uzyskanie planu scalania może być trudniejsze lub może nie być możliwe, używając tylko jednego odgałęzienia - ponieważ polega on na znalezieniu wyrażenia porządkującego, które SQL Server:
- Akceptuje, że wyszukiwanie indeksu dostarczy określoną kolejność, więc sortowanie nie jest potrzebne przed szczytem.
- Z przyjemnością korzysta z operacji scalania, więc nie wymaga sortowania po
TOP
SELECT TOP 10 * FROM YourTable ORDER BY ABS(YourCol - 32) ;
jeszcze prostsze. Nie jest również wydajny.