2009-10-28 97 views
10

Esto es probablemente más fácil de lo que lo estoy haciendo, pero básicamente lo que tengo que hacer es seleccionar la fila que tiene el número más cercano en una columna como un valor específico. Por ejemplo:Seleccione el valor numérico más cercano con la consulta de MySQL

lista de valores en la base de datos de 3 filas de una columna especificada: 10, 15, 16

Si especifico que quiero la fila que está más cerca de 14, se recogería la fila con 15

Además, si hay más de 2 filas que tienen la misma distancia, elija una de ellas al azar.

Respuesta

21

Una opción sería algo a lo largo de las líneas de:

select the_value, 
     abs(the_value - 14) as distance_from_test 
from  the_table 
order by distance_from_test 
limit 1 

Para seleccionar un registro aleatorio, se puede añadir a la cláusula , rand()order by. La desventaja de este método es que no obtiene ningún beneficio de los índices porque tiene que ordenar el valor derivado distance_from_test.

Si tiene un índice en the_value y relaja su requisito de que el resultado sea aleatorio en el caso de los vínculos, puede realizar un par de consultas de rango limitado para seleccionar el primer valor inmediatamente superior al valor de prueba y el primero valor inmediatamente por debajo del valor de la prueba y escoger el que sea más cercano al valor de la prueba:

(
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 
+0

pedante: 'ASC' es la clasificación predeterminado/fin - no es necesario que lo especifique. –

+2

Generalmente lo incluyo en las consultas que escribo, no sea que vuelva más tarde y creo que olvidé poner un orden de clasificación en :-). –

3

para utilizar un índice, podría seleccionar el valor mínimo por encima del objetivo, y el valor máximo a continuación. Entonces solo tienes dos valores para verificar.

2

¿Cómo manejarías los desempates? Debido a esto sólo se llevará a la primera:

SELECT t.col 
    FROM TABLE t 
ORDER BY ABS(t.col - @val) 
    LIMIT 1 

Índice alternativa segura:

SELECT xt.col 
    FROM (SELECT t.col, 
       ABS(t.col - @val) 'diff' 
      FROM TABLE t) xt 
ORDER BY xt.diff 
    LIMIT 1 
Cuestiones relacionadas