Supondo que a coluna esteja indexada, o seguinte deve ser razoavelmente eficiente.
Com duas buscas de 10 linhas e, em seguida, uma espécie de (até) 20 retornadas.
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
(ou seja, potencialmente algo como o abaixo)
Ou outra possibilidade (que reduz o número de linhas classificadas para no máximo 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: O plano de execução acima foi para a definição de tabela simples
CREATE TABLE [dbo].[YourTable](
[YourCol] [int] NOT NULL CONSTRAINT [SomeIndex] PRIMARY KEY CLUSTERED
)
Tecnicamente, a Classificação na ramificação inferior não deve ser necessária, pois também é solicitada por Diff, e seria possível mesclar os dois resultados ordenados. Mas não consegui esse plano.
A consulta tem ORDER BY Diff ASC, YourCol ASC
e não apenasORDER BY YourCol ASC
, porque foi isso que acabou trabalhando para se livrar da Classificação na parte superior do plano. Eu precisava adicionar a coluna secundária (mesmo que ela nunca mude o resultado, pois YourCol
será o mesmo para todos os valores com o mesmo Diff), para que ela passe pela junção de mesclagem (concatenação) sem adicionar uma Classificação.
O SQL Server parece capaz de inferir que um índice no X procurado em ordem crescente entregará linhas ordenadas por X + Y e nenhuma classificação é necessária. Mas não é possível inferir que a deslocação do índice em ordem decrescente fornecerá linhas na mesma ordem que YX (ou mesmo apenas um menos menos X). Ambas as ramificações do plano usam um índice para evitar uma classificação, mas a TOP 10
ramificação inferior é classificada porDiff
(mesmo que já estejam nessa ordem) para obtê-las na ordem desejada para a mesclagem.
Para outras consultas / definições de tabela, pode ser mais complicado ou impossível obter o plano de mesclagem com apenas uma espécie de uma ramificação - pois se baseia em encontrar uma expressão de ordenação que o SQL Server:
- Aceita que a busca do índice forneça a ordem especificada para que nenhuma classificação seja necessária antes da parte superior.
- Tem o prazer de usar na operação de mesclagem, portanto não requer classificação após o
TOP
SELECT TOP 10 * FROM YourTable ORDER BY ABS(YourCol - 32) ;
ainda mais simples. Também não é eficiente.