For a rough measure I would try something like the following (only Euclidean geometry, it doesn't take into account the Earth curvature or problems like this).
First you could compute the difference between the user's coordinates and the coordinates of places in the database. Like this:
distLat = abs(userLat - placeLat)
distLong = abs(userLong - placeLong)
Then I would compute the distance between the two points using Pythagora's theorem. So:
distance = squareRoot(distLat * distLat + distLong * distLong)
You can compare the distances of all places in the database and take the minimum, which teoreticaly is the place nearest to the user's position.
If you use MySQL I think that a query like this should work:
SELECT * FROM places ORDER BY MIN(SQRT((p.latitude - userLatitude) * (p.latitude - userLatitude) + (p.longitude - userLongitude) * (p.longitude - userLongitude))) LIMIT 1
Beware that this query could be very slow depending on how many places you have, because it needs to read all the rows in the table and compute the distance for each one. Indexes have no effects.
Anyway, for this kind of problems you should better use GIS or databases with good geospatial extensions. MySQL geospatial extension is not very powerful, even in MySQL 5.6. It has a ST_DISTANCE
function but still uses Euclidean geometry which is not very accurate for calculation on a spherical surface like the Earth. Anyway, if you use MySQL 5.6, I think that it should be better to use the ST_DISTANCE
function, which is for sure much more optimized than doing calculations "manually" in the query.
See also this article for a deep explanation and more examples: http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc
EDIT
As requested by the OP, I add more details on how to deal with negative coordinates.
Negative coordinates are generally not a big issue. I will try to explain this with some examples.
Take for example the coordinates of the Brooklyn bridge: 40.704391, -73.994675
.
With the above formula, the distance of the Brooklyn bridge from the Statue of Liberty is:
sqrt((40.704391 - 40.689167)^2 + (-73.994675 - -74.044444)^2) = 0.052045399
Now consider the distance between the Statue of Liberty and the Brooklyn Bowl (coordinates 40.7179666, -73.9670125
), that is:
sqrt((40.7179666 - 40.689167)^2 + (-73.9670125 - -74.044444)^2) = 0.082613886
As you can see the distance of the Brooklyn Bowl from the Statue of Liberty is bigger than the distance of the Brooklyn Bridge. It is correct since the Brooklyn Bowl is 4 miles away from the Statue of Liberty, while the Brooklyn Bridge is only 1 mile away from it.
In this example both the two points has a negative longitude. But the formula works even if one of the two has positive coordinates. For example, the distance between the Statue of Liberty and the Tour Eiffel (Paris, coordinates 48.858360, 2.294460
), is:
sqrt((48.858360 - 40.689167)^2 + (2.294460 - -74.044444)^2) = 76.77476134
Then calculate also the distance between the Statue of Liberty and the Colosseum (Rome, coordinates 41.890238, 12.492242
):
sqrt((41.890238 - 40.689167)^2 + (12.492242 - -74.044444)^2) = 86.54502063
As you can see it works, the distance of the Colosseum is bigger since it is about 8000km away from the Statue of Liberty, while the Tour Eiffel is about 800 km closer.
The only issue I see is when you have to calculate the distance between two places that are in the far east and in the far west respectively. The above formula will give you a very high distance, but actually the they could be very close. Take for example Anchorage, a city in Alaska (coordinates 61.252240, -149.896769
), and Beringovskij, a city in the very east of Russia (coordinates 63.049797, 179.310011
). They have a distance of only about 1500 km but with the above formula you get:
sqrt((61.252240 - 63.049797)^2 + (-149.896769 - 179.310011)^2) = 329.2116875
Definitely a too high value for only 1500 km: I would expect something less than 50.
The problem is that the formula calculates the distance taking the central meridian as a reference point, that is the meridian with a 0 degrees latitude. This is good until the distance is "no more that half the Earth".
I think that a solution could be to calculate two distances.
The first with a reference point of 0 degrees: it is what the above formula does.
The second with a reference point of 180 degrees. It's like calculating the distance on a world map shifted by 180 degrees, like this: http://www.bouwman.com/world/Formilab-180.html.
And then take the minimum of these two distances.
Thus the formula becomes a little more complex:
distance = squareRoot(min((userLat - placeLat)^2, (userLat - placeLat - 360)^2) + (userLong - placeLong)^2)
Note that we subtract 360 because it is the distance between the degree -180 and the degree 180.
With this new formula we get correct results for places that are more then 180 degrees away from each other, and we get also the same result given by the previous formula when comparing places that are less then 180 degrees away from each other. The calculate distance Anchorage - Beringovskij is now: 30.84564166
.
Of course, as I have already said, this is not an exact method for calculating distances. You can take a look at this article for more "scientific" techniques: https://en.wikipedia.org/wiki/Geographical_distance :D