2012-01-12 32 views
8

tengo esto en una tabla de MySQL:¿Por qué esta consulta SQL no devuelve ningún resultado que compare los números de coma flotante?

enter image description here

id y bolag_id son int. lat y lngitude son double.

Si uso la columna de la lngitude, se devuelve ningún resultado:

lngitude Consulta:SELECT * FROM location_forslag WHERE lngitude = 13.8461208

Sin embargo, si uso la columna de la lat, que hace resultados de retorno:

lat Consulta:SELECT * FROM location_forslag WHERE lat = 58.3902782

¿Cuál es el problema con la columna lngitude?

+0

intente 'WHERE lngitude ENTRE 13.8461208 Y 13.8461209'. – Benoit

+0

@Benoit funciona si lo cambio a 13.8461207 Y 13.8461208 –

Respuesta

9

No es generalmente una buena idea comparar los números de punto flotante con = es igual operador.

Para su aplicación, debe tener en cuenta lo cerca que se quiere que la respuesta sea.

1 grado es de aproximadamente 112 km, y 0,00001 grados es de aproximadamente 1,1 metros (en el ecuador). ¿Realmente quieres que tu aplicación diga "no igual" si dos puntos son diferentes por 0.00000001 grados = 1mm?

set @EPSLION = 0.00001 /* 1.1 metres at equator */ 

SELECT * FROM location_forslag 
WHERE `lngitude` >= 13.8461208 [email protected] 
AND `lngitude` <= 13.8461208 + @EPSILON 

Esto devolverá puntos donde lngitude está dentro @epsilon grados del valor deseado. Debe elegir un valor para épsilon que sea apropiado para su aplicación.

+2

utilizando la palabra clave SQL BETWEEN no está mal en este caso (OMI más legible). – Benoit

+1

¿Qué le parece usar 'lngitude' LIKE 13.8461208? ¿Podría ser eso una solución? –

+0

@Lille_skutt: No, debe tomar una decisión deliberada sobre la precisión que desea, y hacer sus comparaciones explícitamente. La base de datos no tiene nada que lo ayude aquí, a menos que tenga algunas extensiones SIG instaladas. – Ben

4

Floating points are irritating ....

WHERE ABS(lngitude - 13.8461208) < 0.00000005 
+0

Eso funciona. ¿Entonces es solo una coincidencia que funcionó con la otra columna? ¿Puedo almacenar esto en un mejor tipo de datos? –

+0

Un tipo de datos 'DECIMAL' es exacto en versiones recientes de MySQL, vea el enlace. – Wrikken

+0

El tipo de datos está bien, el problema es que el significado de "igual" depende de la aplicación; en el mundo real no existe tal cosa.En una aplicación de navegación por satélite, igual puede ser "dentro de 10 metros". Para una base de datos de registro de tierras "dentro de 0.05 metros" podría ser suficiente. Construyendo una cocina, podría ser "dentro de 5 mm". – Ben

0

Convierte el flotador a decimal para comparar. Yo tenía el mismo problema y lo resolvió así:

SELECT 
    [dbo].[Story].[Longitude], 
    [dbo].[Story].[Latitude], 
    [dbo].[Story].[Location], 
FROM 
    [dbo].[Story], 
    [dbo].[Places] 
WHERE 
    convert(decimal, [dbo].[Story].[Latitude]) = convert(decimal, [dbo].[Places].[Latitude]) 
    and 
    convert(decimal, [dbo].[Story].[Longitude]) = convert(decimal, [dbo].[Places].[Longitude]) 
    and 
    [dbo].[Places].[Id] = @PlacesID 
    and 
    [dbo].[Story].IsDraft = 0 
ORDER BY 
    [dbo].[Story].[Time] desc 

Mira las 3 primeras filas después de la clausula WHERE. Espero que ayude.

Cuestiones relacionadas