问题
I'm trying to implement a geospacial search in a php application. Currently, I'm using the following query to find points within 10km of a given latitude and longitude:
SELECT * FROM (
SELECT *,
(6378.1 * ACOS(
COS(RADIANS(48.856614)) * COS(RADIANS(latitude))
* COS(RADIANS(2.3522219) - RADIANS(longitude))
+ SIN(RADIANS(48.856614))
* SIN(RADIANS(latitude)))
) AS distance
FROM `destinations_info`
WHERE latitude BETWEEN 48.856614 - (10 / 69)
AND 48.856614 + (10 / 69)
AND longitude BETWEEN 2.3522219 - (10 / (69 * COS(RADIANS(48.856614))))
AND 2.3522219 + (10 / (69 * COS(RADIANS(48.856614))))
) d
WHERE distance <= 10
LIMIT 1
This works fine as long I don't search for the exact latitude and longitude that is stored into the POI's table.
So for example if I have in my poi table the following entry
id name latitude longitude
1 Paris 48.856614 2.3522219000000177
And I call the query with lat = 48.856614
and long = 2.3522219000000177
I won't get any results. As far as I see this happens because the following operation returns NULL and not 0 in mysql:
SELECT (6378.1 * acos(cos(radians(48.856614)) * cos(radians(48.856614)) * cos( radians(2.3522219) - radians(2.3522219)) + sin(radians(48.856614)) * sin(radians(48.856614))))
Running the same in Chrome Calculator I get 0 rad.
Is there something wrong in the query or do I need to include the NULL results as well using "OR IS NULL"
回答1:
IFNULL( ... ),0) AS Distance will also help you to get around the error.
回答2:
The problem is that acos is invoked with a value which is not in the range of -1 and 1, so it returns null.
SELECT cos(radians(48.856614)) * cos(radians(48.856614)) * cos( radians(2.3522219) - radians(2.3522219)) + sin(radians(48.856614)) * sin(radians(48.856614))
1.0000000000000002
It seems to be some sort of rounding issue.
Since, arc cos is defined only between -1 and 1, you probably should pre-check its parameter or be prepared that it can return null if something is wrong with the calculation.
来源:https://stackoverflow.com/questions/28254863/mysql-geospacial-search-using-haversine-formula-returns-null-on-same-point