Hi everyone!
I *think* I've modified this for use with mysql.. since you can't create functions that return a resultset I've changed it to a stored procedure. I'm no SQL guru though, so it would be awesome if someone smarter than me could provide some guidance on improving this if it needs it
Code:
delimiter $$
CREATE PROCEDURE yourdb.getNearbyLocations
(
Latitude decimal(23,20),
Longitude decimal(23,20),
MaxDistance int
)
BEGIN
SET @MaxDistanceDec = MaxDistance;
SET @EarthRadius = 6378.137;
SET @LatRange = (@MaxDistanceDec / 111); -- 111 is number of km in 1 degree lat
SET @LongRange = ((@MaxDistanceDec / 111) / cos(Radians(Latitude)));
SET @MinLatitude = Latitude - @LatRange;
SET @MaxLatitude = Latitude + @LatRange;
SET @MinLongitude = Longitude - @LongRange;
SET @MaxLongitude = Longitude + @LongRange;
-- Search
CREATE TEMPORARY TABLE IF NOT EXISTS GeoNameIDs
(GeoNameID INT, distance INT);
INSERT INTO GeoNameIDs (GeoNameID, Distance)
SELECT GeoNameID,
ROUND(@EarthRadius * ACOS(ROUND(
(SIN(RADIANS(Latitude)) * SIN(RADIANS(geo.Latitude))) +
(COS(RADIANS(Latitude)) * COS(RADIANS(geo.Latitude)) *
COS(RADIANS(geo.Longitude) - RADIANS(Longitude))),15)),0) AS Distance
FROM yourdb.geonames AS geo
WHERE -- Below is rough proximity search to super speed the query up
(Latitude >= @MinLatitude AND Latitude <= @MaxLatitude AND Longitude >= @MinLongitude AND Longitude <= @MaxLongitude)
-- Below should result in accurate proximity search
AND ROUND(@EarthRadius * ACOS(ROUND(
(SIN(RADIANS(Latitude)) * SIN(RADIANS(geo.Latitude))) +
(COS(RADIANS(Latitude)) * COS(RADIANS(geo.Latitude)) *
COS(RADIANS(geo.Longitude) - RADIANS(Longitude))),15)),0) <= @MaxDistanceDec
ORDER BY 2 ASC;
SELECT * FROM GeoNameIDs;
DROP TABLE GeoNameIDs;
END;
$$
delimiter ;
Code:
call yourdb.getNearByLocations(33.124560000000, -87.057220000000, 2)