Unter der Annahme, dass die Spalte indexiert ist, sollte das Folgende einigermaßen effizient sein.
Mit zwei Suchläufen von 10 Zeilen und dann einer Art von (bis zu) 20 zurückgegeben.
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
(dh möglicherweise so etwas wie das unten)
Oder eine andere Möglichkeit (die die Anzahl der sortierten Zeilen auf maximal 10 reduziert)
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
Hinweis: Der oben angegebene Ausführungsplan betraf die einfache Tabellendefinition
CREATE TABLE [dbo].[YourTable](
[YourCol] [int] NOT NULL CONSTRAINT [SomeIndex] PRIMARY KEY CLUSTERED
)
Technisch gesehen sollte die Sortierung im unteren Zweig ebenfalls nicht erforderlich sein, da auch diese von Diff sortiert wird und es möglich wäre, die beiden geordneten Ergebnisse zusammenzuführen. Aber ich konnte diesen Plan nicht bekommen.
Die Abfrage hat ORDER BY Diff ASC, YourCol ASC
und nicht nur ORDER BY YourCol ASC
, weil genau das dazu geführt hat , dass die Sortierung im obersten Zweig des Plans entfernt wurde. Ich musste die sekundäre Spalte hinzufügen (obwohl dies das Ergebnis nie ändern YourCol
wird, da es für alle Werte mit demselben Diff gleich ist), damit es die Zusammenführungsverknüpfung (Verkettung) durchlaufen würde, ohne eine Sortierung hinzuzufügen.
SQL Server scheint darauf schließen zu können, dass ein Index für X, der in aufsteigender Reihenfolge gesucht wird, Zeilen liefert, die nach X + Y sortiert sind, und keine Sortierung erforderlich ist. Es kann jedoch nicht abgeleitet werden, dass das Durchlaufen des Index in absteigender Reihenfolge Zeilen in derselben Reihenfolge wie YX (oder sogar nur unäres minus X) liefert. Beide Zweige des Plans verwenden einen Index, um eine Sortierung zu vermeiden. Die Zweige TOP 10
im unteren Zweig werden dann sortiert Diff
(obwohl sie sich bereits in dieser Reihenfolge befinden), um sie für die Zusammenführung in der gewünschten Reihenfolge abzurufen.
Für andere Abfragen / Tabellendefinitionen ist es möglicherweise schwieriger oder nicht möglich, den Zusammenführungsplan mit nur einer Art von Zweig abzurufen, da SQL Server darauf angewiesen ist, einen Sortierausdruck zu finden:
- Akzeptiert, dass die Indexsuche die angegebene Reihenfolge liefert, sodass keine Sortierung vor dem Anfang erforderlich ist .
- Ist gerne in der Merge-Operation zu verwenden, erfordert also keine Sortierung nach dem
TOP
SELECT TOP 10 * FROM YourTable ORDER BY ABS(YourCol - 32) ;
noch einfacher gebrauchen . Auch nicht effizient.