2010-02-02 8 views
12

Mam system Joomla i próbuję zmienić wyszukiwanie, aby poprawnie znaleźć wartości zmiennoprzecinkowe w bazie danych.Sprawdź równość w polach MySQL Float

Tak, mam kwerendę, która jest wbudowana w czasie wykonywania, który wygląda mniej więcej tak:

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

to nie zadziała, to nigdy nie pasuje nic, chociaż widzę rekordy w db z tej wartości tam.

Więc starałem się po prostu to zrobić w zamian:

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

bez powodzenia, więc potem próbował odlewania do przecinku (float nie działa z jakiegoś powodu), więc próbowałem to:

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

Brak kości ...

Należy pamiętać, że> = lub < = zwraca odpowiednich wyników, tylko < => daje mi problemów.

Jak uzyskać tutaj równość?

Odpowiedz

12

Zwykle z tego typu pytania jest dobry, aby zapewnić mały przykład do replikacji wyników.

Zazwyczaj testowanie dokładnych wartości zmiennoprzecinkowych jest złym pomysłem, ponieważ precyzja zmiennoprzecinkowa nie jest nauką ścisłą. Znacznie lepiej jest używać pewnej tolerancji.

create table foo1 (col1 float); 

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

Tak, w tym przypadku staram się znaleźć "ciężar" czegoś, co umieszcza użytkownik, ale chcą dopasować dokładne liczby, więc muszę spełnić ten wymóg. – Joseph

+2

Czy w tabeli wymagane jest posiadanie typu float? Zwykle, gdy użytkownicy chcą dokładnych liczb ułamkowych (na przykład pieniędzy), dziesiętny typ danych jest znacznie lepszym wyborem. Przez wiele lat będziesz mieć problemy z zaokrąglaniem. Pomyśl o tym. A jeśli to faktycznie pieniądze, przez przypadek, nie marnuj czasu i przeprojektuj dziesiętnie PRAWO TERAZ. Zaufaj mi, mówię tutaj z doświadczenia. –

+0

Zgadzam się z Seva. Pierwszą rzeczą, którą robię przed rozpoczęciem pracy nad nową bazą danych, jest uruchomienie następującego zapytania i sprawdzenie, ile kolumn zmiennoprzecinkowych jest używanych. WYBIERZ DATA_TYPE, COUNT (*) JAK MIESZAĆ Z KATALOGU INFORMACJI. KOLUMNY GDZIE TABELA_SCHEMA NIE IN ("informacja_schemat", "mysql") GRUPA PRZEZ DATA_TYPE ORDER PRZEZ Mycount DESC Jeśli stwierdzę, że liczba podwójnych, zmiennoprzecinkowych, bigintów i bloków jest zbyt wysokie, zakładam, że będzie wiele problemów. Jeśli liczba dziesiętna, data, data/godzina, tinyint jest zbyt mała (lub zerowa), to znowu pojawia się problem :) – shantanuo

1

Rozważ to:

where abs(some_float_field) - 2.18 < 0.001 
+0

Rozumiem problem precyzji. W moim przypadku nie dbam o precyzję po drugim miejscu po przecinku. Chcę tylko znaleźć coś, co pasuje, nie chcę robić arytmetyki. – Joseph

4

Znalazłem sposób na sprawdzenie, co moi użytkownicy postrzegają jako równość.

musiałem konwertować pole do łańcucha znaków i przetestować zestawy znaków, więc to działa dobrze dla nich:

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

wiem to jest to stary post, ale jeśli nie chcesz precyzyjny porównanie po prostu użyj LIKE lub NIE JAK:

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

To porównanie ciągów! Zwraca również wiersze takie jak '12.18' itd. – xmedeko

+0

@xmedeko autor prosi o znalezienie sposobu na uzyskanie wszystkich wartości nie równych 2.18. Nawet jeśli jest to porównanie łańcuchowe, 12,18 nie jest równe 2,18, więc nie ma problemu z powrotem do 12.18. Również jeśli przyjrzysz się memu zapytaniu, zauważysz, że nie używam znaku procentu i dlatego 12,18 to poprawna wartość do zwrócenia. – Shaolin

+0

@xmedeko nie ma nic do edycji. Jeśli chcesz, aby tylko zmienne były równe 2.18, po prostu użyj LIKE bez znaku% i pobierzesz tylko 2,18. 'create table test (price float) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB; wstaw do wartości testowych (2.18), (12.18), (32.18), WYBIERZ * Z testu gdzie cena LIKE '2.18';' – Shaolin