Suponiendo que la columna está indexada, lo siguiente debería ser razonablemente eficiente.
Con dos búsquedas de 10 filas y luego una especie de (hasta) 20 devueltas.
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
(es decir, potencialmente algo como lo siguiente)
U otra posibilidad (que reduce el número de filas ordenadas a un máximo de 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: el plan de ejecución anterior era para la definición de tabla simple
CREATE TABLE [dbo].[YourTable](
[YourCol] [int] NOT NULL CONSTRAINT [SomeIndex] PRIMARY KEY CLUSTERED
)
Técnicamente, la Clasificación en la rama inferior tampoco debería ser necesaria, ya que también lo ordena Diff, y sería posible fusionar los dos resultados ordenados. Pero no pude conseguir ese plan.
La consulta tiene ORDER BY Diff ASC, YourCol ASC
y no solo ORDER BY YourCol ASC
, porque eso fue lo que terminó trabajando para deshacerse de la Clasificación en la rama superior del plan. Necesitaba agregar la columna secundaria (aunque nunca cambiará el resultado comoYourCol
que será el mismo para todos los valores con el mismo Diff), por lo que pasaría por la combinación de fusión (concatenación) sin agregar un Ordenar.
SQL Server parece inferir que un índice en X buscado en orden ascendente entregará filas ordenadas por X + Y y no es necesario ordenarlas. Pero no puede inferir que recorrer el índice en orden descendente generará filas en el mismo orden que YX (o incluso solo unario menos X). Ambas ramas del plan usan un índice para evitar una clasificación, pero las TOP 10
de la rama inferior se ordenan por Diff
(aunque ya estén en ese orden) para obtener el orden deseado para la fusión.
Para otras consultas / definiciones de tabla, puede ser más complicado o imposible obtener el plan de fusión con solo una especie de rama, ya que se basa en encontrar una expresión de orden que SQL Server:
- Acepta que la búsqueda de índice proporcionará el orden especificado, por lo que no se necesita ninguna clasificación antes de la parte superior.
- Es feliz de usar en la operación de fusión, por lo que no requiere ningún tipo después
TOP
SELECT TOP 10 * FROM YourTable ORDER BY ABS(YourCol - 32) ;
aún más simple. Tampoco eficiente.