2011-09-01 38 views
6

Estoy usando mySQL y CodeIgniter. Tengo algunos números de punto flotante en mi base de datos comocómo obtener el valor más cercano de la base de datos en mysql

  • 8,3456
  • 8,5555
  • 4,5556

quiero ...

SELECT * FROM table WHERE value = $myvalue 

pero no puedo use value = $myvalue en mi consulta SELECT porque $myvalue no es exactamente igual a los valores de la base de datos. Necesito obtener el valor más cercano a $myvalue de la base de datos.

Si $myvalue es 5, quiero seleccionar el valor 4.5556.

¿Cómo puedo hacer esto en mySQL?

+0

si tiene algunas filas, entonces las respuestas hacia la parte superior serán suficientes; sin embargo, si tiene millones de filas, no las recomendaría, ya que escanearán toda la tabla, en cambio, vea mi respuesta al final (trade- fuera de legibilidad, ya que la consulta es mucho más larga, pero también mucho más rápida) –

Respuesta

2

Tome el primer valor de entre los siguientes:

select * from table order by abs(value - $myvalue); 
0
SELECT * FROM table1 ORDER BY ABS(value - '$myvalue') LIMIT 1 
12

Asumiendo que usted tiene una tolerancia del 10% (+/-) podría intentar algo como:

select * from table 
where value >= ($myvalue * .9) and value <= ($myvalue * 1.1) 
order by abs(value - $myvalue) limit 1 

ligeramente modificada robar de otros: esto debería devolver el resultado más cercano en el rango de tolerancia asumido. (Además, acabo de notar que estaba incorrecto, disculpas, ahora debería funcionar).

+0

¿Qué sucede si el $ mivalor más cercano es más que su% arbitrario lejos de cualquier valor? – Bohemian

+1

El requisito original no es muy claro. Por supuesto, si no hay un "rango aceptado", puede decir que 10000000000 está lo suficientemente cerca de "1", suponiendo que no hay nada mejor en su base de datos. En este caso, puede soltar la parte "dónde". –

+1

Tenga en cuenta que esto fallará si '$ Myvalue' es 0. Si realmente desea hacer esto, debe agregar' OR (($ mivalor> = (valor * .9)) AND ($ mivalor <= (valor * 1.1))) ' – Johan

0

Leer esta página http://dev.mysql.com/doc/refman/5.1/en/mathematical-functions.html#function_round

pero su selecto se vería así

select value from table where ROUND(value) = $myvalue 
+3

¿Qué sucede si el '$ myvalue' más cercano está a más de 1 de cualquier valor? – Bohemian

+0

@Bohemian - en algún momento va a necesitar un punto de corte para igualar el valor – Rob

+0

@Bohemian, no, eso no depende completamente de su aplicación, y ** si ** necesita un punto de corte, siempre debe ser un porcentaje de los valores originales. ¿Qué sucede si no está tratando con '8.12', sino con' 15,481,254,454,875,544,545.1' en su lugar? – Johan

8
select * 
from table 
order by abs(value - $myvalue) 
limit 1 
+2

Probablemente realiza una exploración de tabla (lenta). –

0

Por desgracia, creo que su base de datos, probablemente, va a hacer un escaneo completo de tabla para las soluciones que implican abs, por lo que será (muy) lento una vez que su mesa crezca. Se puede encontrar una solución de ejecución rápida en este earlier thread.

2
(
select * 
from  table 
where value >= $myvalue 
order by value asc 
limit 1 
) 
union 
(
select * 
from  table 
where value < $myvalue 
order by value desc 
limit 1 
) 
order by abs(value - $myvalue) 
limit 1 

Esto puede parecer contrario a la intuición, pero la velocidad será mayor que las otras consultas mostrados hasta el momento.

Esto se debe a que una consulta greater than y less than es más rápida.

Luego hacer un ABS en dos valores no es nada.

Esto le dará el retorno más rápido en una sola consulta que se me ocurra.

Hacer un ABS en una mesa completa será lento ya que escaneará toda la tabla.

+0

@ LoïcFaure-Lacroix También elimine la * mierda * de la publicación en lugar de simplemente corregir la ortografía. Saludos. –

+0

@BhargavRao una oración termina con un punto por cierto. Y eso es exactamente lo que hice, de lo que estás hablando es de la escritura leet como sh1t ... –

+1

@ LoïcFaure-Lacroix Lo que Bhargav quiso decir es que editaste contenido de ofensas inútiles en contenido ofensivo inútil, que no es una mejora en absoluto. Cuando te enfrentes a insultos o palabras malas, simplemente edítalos (sea cual sea la forma en que estén). Por favor, ven [al chat] (https://chat.stackoverflow.com/rooms/41570/so-close-vote-reviewers) si deseas continuar el debate. –

0

Prueba esto:

SELECT *,abs((columnname -Yourvalue)) as near 
    FROM table 
WHERE order by near limit 0,1 
1

Obtener el valor más grande similar a $ val:

SELECT * FROM tab WHERE val <= $val ORDER BY val DESC LIMIT 1 

Obtener el valor más pequeño similar a $ val:

SELECT * FROM tab WHERE val >= $val ORDER BY val LIMIT 1 

obtener el valor más cercano similar a $ val en cualquier dirección:

SELECT * FROM tab ORDER BY abs(val - $val) LIMIT 1 
Cuestiones relacionadas