Finding geographical distances between two points in MySQL 5
For a project I’m working on I needed to find the distances between two points to be able to let users ask the application questions like: “How many points of type X (coworkers, jobs, gas stations, donutshops) are within a radius of point y (my home, my office, my previous donut shop). Or what is the nearest point x from point y.
I solved this problem with a stored procedure. Below the click are two stored procedures that achieve the same goal.
In each of these procedures change “TABLE_WITH_POINTS alias” with the table (and it’s alias) that has your geopgraphical points in them. Change “alias.” with the tables alias.
This first one returnes all points y from the initial point x. As indicated by the latitude and longtitude input parameters ordered by distance (in kilometers).
CREATE PROCEDURE distance(IN startlat double, IN startlon double) BEGIN SELECT alias.*, ( ( (acos( sin((startlat*pi()/180))*sin((alias.lat*pi()/180)) + cos((startlat*pi()/180))*cos((alias.lat*pi()/180)) * cos(((startlon - alias.lon)*pi()/180))))*180/pi() )*60*1.1515*1.609344 ) as distance FROM TABLE_WITH_POINTS alias WHERE alias.lat IS NOT NULL AND alias.lon IS NOT NULL AND alias.lat != '' AND alias.lon != '' ORDER BY distance ASC; END $$
The second procedure only gives you the points within the given distance in kilometers
CREATE PROCEDURE distance(IN startlat double, IN startlon double, IN dist int) BEGIN SELECT alias.*, ( ( (acos( sin((startlat*pi()/180))*sin((alias.lat*pi()/180)) + cos((startlat*pi()/180))*cos((alias.lat*pi()/180)) * cos(((startlon - alias.lon)*pi()/180))))*180/pi() )*60*1.1515*1.609344 ) as distance FROM TABLE_WITH_POINTS alias WHERE alias.lat IS NOT NULL AND alias.lon IS NOT NULL AND alias.lat != '' AND alias.lon != '' HAVING distance < dist ORDER BY distance ASC; END $$
4 Comments »
RSS feed for comments on this post. TrackBack URL
Finding geographical distances between two points in MySQL 5…
[...]For a project I’m working on I needed to find the distances between two points to be able to let users ask the application questions like: “How many points of type X (coworkers, jobs, gas stations, donutshops) are within a radius of point y (m…
Have you considered utilizing the spatial features of MySql … there is a Distance() function that would give you the same result.
Yes I have, and the examples I found look promising. However for a variety of reasons this isn’t a feasibile option for the company. This meant I had to solve it the old-fashioned mathematical way
With some changes you can run this as a regular query but creating a procedure out of it and idexing the lat/lon fields increases the speed a lot. To check one point against 3000 other records takes only 0.003 seconds on my MacBook.
You can also cache or pre-calculate most of these values and index these pre-calculations. This will make for a huge speed increase.
I had to write something very similar for work not long ago, I think mines a little different, will try digging it up later and posting back if i can find it.