2010-02-02 9 views
12

Tengo un sistema Joomla y estoy tratando de cambiar la búsqueda para que encuentre correctamente los valores de coma flotante en la base de datos.Verificar la igualdad en un campo flotante de MySQL

lo tanto, tengo una consulta que se construyó en tiempo de ejecución que se ve algo como esto:

select 'column1' 
from 'some_table' 
where 'some_float_field' <=> '2.18' 

Esto no funciona, nunca coincide con todo, a pesar de que veo registros en el PP con este valor ahí.

así que traté de hacer esto solo lugar:

select 'column1' 
from 'some_table' 
where 'some_float_field' <=> 2.18 

No hubo suerte, por lo que entonces traté de fundición a un decimal (float no funciona por alguna razón), así que probamos este:

select 'column1' 
from 'some_table' 
where 'some_float_field' <=> CAST('2.18' AS DECIMAL(20, 2)) 

No hay dados ...

Tenga en cuenta que> = o = < devuelve los resultados apropiados, simplemente < => me da problemas.

¿Cómo consigo que la igualdad funcione aquí?

Respuesta

12

lo general, con este tipo de preguntas es bueno para proporcionar un pequeño ejemplo para replicar sus resultados.

Normalmente, la prueba de los valores exactos de flotación es una mala idea, ya que la precisión de punto flotante no es una ciencia exacta. Es mucho mejor usar algo de tolerancia.

create table foo1 (col1 float); 

insert into foo1 values (2.18); 
select * from foo1 where abs(col1-2.18) <= 1e-6 
+0

Sí, en este caso, estoy tratando de encontrar un "peso" de algo que el usuario está poniendo, pero ellos quieren hacer coincidir los números exactos, así que tengo que cumplir con los requisitos. – Joseph

+2

¿Es un requisito del usuario tener un tipo de datos float en la tabla? Normalmente, cuando los usuarios desean números fraccionarios exactos (por ejemplo, dinero), el tipo de datos decimales es una opción mucho mejor. Obtendrá problemas de redondeo en los próximos años. Piénsalo. Y si realmente es dinero, por casualidad, no pierdas el tiempo y rediseña el decimal AHORA MISMO. Confía en mí, hablo por experiencia aquí. –

+0

Estoy de acuerdo con Seva. Lo primero que hago antes de empezar a trabajar en una nueva base de datos es ejecutar la siguiente consulta y encontrar cuántas columnas flotantes se usan. SELECT DATA_TYPE, COUNT (*) COMO mycount FROM information_schema.COLUMNS WHERE TABLE_SCHEMA NOT IN ('information_schema', 'mysql') GROUP BY DATA_TYPE ORDER BY mycount DESC Si encuentro que el número de double, float, bigint y blobs es demasiado alto entonces supongo que habrá muchos problemas. Si el número de decimal, fecha, fecha y hora, tinyint es demasiado pequeño (o nill), entonces nuevamente hay un problema :) – shantanuo

1

Considera:

where abs(some_float_field) - 2.18 < 0.001 
+0

Entiendo el problema de la precisión. En mi caso, no me importa la precisión más allá del segundo lugar decimal. Solo quiero encontrar algo que coincida, no estoy buscando hacer ninguna aritmética. – Joseph

4

Encontré una manera de verificar lo que mis usuarios ven como igualdad.

tuve que convertir el campo a una cadena de caracteres y probar los juegos de caracteres, por lo que este funciona bien para ellos:

select 'column1' 
from 'some_table' 
where CAST('some_float_field' AS CHAR) <=> '2.18' 
0

Sé que estas es una entrada antigua, pero si usted no quiere una precisa comparación simplemente usar LIKE o NOT LIKE:

select 'column1' 
from 'some_table' 
where 'some_float_field' NOT LIKE '2.18' 
+0

¡Es una comparación de cuerdas! Devuelve también filas como '12.18', etc. – xmedeko

+0

@xmedeko, el autor pregunta para encontrar una forma de obtener todos los valores no iguales a 2.18. Incluso si se trata de una comparación de cadenas, 12.18 no es igual a 2.18, por lo que no hay problema para devolver 12.18. Además, si miras más de cerca a mi consulta, notarás que no utilizo el signo de porcentaje y esta es la razón por la cual 12.18 es un valor correcto para devolver. – Shaolin

+0

@xmedeko no hay nada que editar. Si solo quiere flotar equivale a 2.18, simplemente use LIKE sin el signo% y solo obtendrá 2.18. 'create table test (price float) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB; insert into test values ​​(2.18), (12.18), (32.18); SELECT * FROM prueba donde LIKE '2.18';' – Shaolin

Cuestiones relacionadas