Uma opção seria algo como:
select the_value,
abs(the_value - 14) as distance_from_test
from the_table
order by distance_from_test
limit 1
Para selecionar um registro aleatório, você pode adicionar
, rand()
para o order by
cláusula. A desvantagem desse método é que você não obtém nenhum benefício dos índices porque precisa classificar pelo valor derivado distance_from_test
. Se você tiver um índice em
the_value
e você relaxa sua exigência de que o resultado seja aleatório no caso de empates, você pode realizar um par de consultas de intervalo limitado para selecionar o primeiro valor imediatamente acima do valor de teste e o primeiro valor imediatamente abaixo do valor de teste e escolher o que estiver mais próximo para o valor de teste:(
select the_value
from the_table
where the_value >= 14
order by the_value asc
limit 1
)
union
(
select the_value
from the_table
where the_value < 14
order by the_value desc
limit 1
)
order by abs(the_value - 14)
limit 1