2012-01-12 12 views
8

mam to w tabeli mysql:Dlaczego to zapytanie sql nie zwraca żadnych wyników porównujących liczby zmiennoprzecinkowe?

enter image description here

id i bolag_idint. lat i lngitudedouble.

Jeśli używam kolumnie lngitude brak wyników zwrócone są:

lngitude Zapytanie:SELECT * FROM location_forslag WHERE lngitude = 13.8461208

Jednakże, jeśli mogę użyć kolumny lat, to robi wyników Powrót:

lat Zapytanie:SELECT * FROM location_forslag WHERE lat = 58.3902782

Na czym polega problem z kolumną lngitude?

+0

spróbuj "GDZIE LICZBA MIĘDZY 13.8461208 I 13.8461209". – Benoit

+0

@Benoit działa, jeśli zmienię go na 13.8461207 I 13.8461208 –

Odpowiedz

9

To nie jest ogólnie dobry pomysł, aby porównać liczb zmiennoprzecinkowych z = równa operatora.

dla danej aplikacji, należy wziąć pod uwagę, jak blisko chcesz być odpowiedź.

1 stopień to około 112 km, a 0,00001 stopnia to około 1,1 metra (na równiku). Czy naprawdę chcesz, aby aplikacja mówiła "nie równa się", jeśli dwa punkty różnią się o 0.00000001 stopni = 1 mm?

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

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

Spowoduje to zwrócenie punktów, w których lng jest w zakresie @epsilon stopni od pożądanej wartości. Powinieneś wybrać wartość dla epsilon, która jest odpowiednia dla twojej aplikacji.

+2

za pomocą słowa kluczowego SQL BETWEEN w tym przypadku nie jest zły (bardziej czytelny IMO). – Benoit

+1

Co powiesz na używanie 'lngitude' LIKE 13.8461208? Czy to może być rozwiązanie? –

+0

@Lille_skutt: Nie, musisz świadomie podjąć decyzję, jaka dokładność chcesz, i dokonać wyraźnych porównań. Baza danych nie ma tu nic do zaoferowania - chyba że masz zainstalowane jakieś rozszerzenia GIS. – Ben

4

Floating points are irritating ....

WHERE ABS(lngitude - 13.8461208) < 0.00000005 
+0

To działa. Więc to tylko zbieg okoliczności, że działał z drugą kolumną? Czy mogę zapisać to w lepszym typie danych? –

+0

Typ danych 'DECIMAL' jest dokładny w najnowszych wersjach MySQL, patrz link. – Wrikken

+0

Typ danych jest w porządku, problem polega na tym, że znaczenie "równości" zależy od zastosowania - w świecie rzeczywistym nie ma czegoś takiego.W aplikacji nawigacji satelitarnej wartość ta może wynosić "w promieniu 10 metrów". Dla bazy danych rejestru nieruchomości "w odległości 0,05 metra" może być wystarczająco dobre. Budując kuchnię, może to być "w granicach 5 mm". – Ben

0

Konwertuj zmiennoprzecinkowe na dziesiętne w celu porównania. Miałem ten sam problem i rozwiązano go w następujący sposób:

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 

Spójrz na pierwsze 3 rzędy po klauzuli WHERE. Mam nadzieję, że to pomaga.

Powiązane problemy