Note: Although I use a zipcode database with Dutch zipcodes, this question is country independent.
I have a database with every zipcode in the Netherlands +
You want to do something like this:
SELECT zipcode FROM zipcodes WHERE DistanceFormula(lat, long, 4.808855, 52.406332) < $range
It may be slow if your table of zip codes is large. You may also want to check out the geospatial extensions for MySQL.
You have to use something called the Haversine formula:
$sql = "
SELECT zipcode
FROM zipcodes
WHERE ".mysqlHaversine($lat, $lon, $distance)."
";
And the formula:
function mysqlHaversine($lat = 0, $lon = 0, $distance = 0)
{
if($distance > 0)
{
return ('
((6372.797 * (2 *
ATAN2(
SQRT(
SIN(('.($lat*1).' * (PI()/180)-latitude*(PI()/180))/2) *
SIN(('.($lat*1).' * (PI()/180)-latitude*(PI()/180))/2) +
COS(latitude * (PI()/180)) *
COS('.($lat*1).' * (PI()/180)) *
SIN(('.($lon*1).' * (PI()/180)-longitude*(PI()/180))/2) *
SIN(('.($lon*1).' * (PI()/180)-longitude*(PI()/180))/2)
),
SQRT(1-(
SIN(('.($lat*1).' * (PI()/180)-latitude*(PI()/180))/2) *
SIN(('.($lat*1).' * (PI()/180)-latitude*(PI()/180))/2) +
COS(latitude * (PI()/180)) *
COS('.($lat*1).' * (PI()/180)) *
SIN(('.($lon*1).' * (PI()/180)-longitude*(PI()/180))/2) *
SIN(('.($lon*1).' * (PI()/180)-longitude*(PI()/180))/2)
))
)
)) <= '.($distance/1000). ')');
}
return '';
}
Usually I do not use code without understanding the way it works first, but I must confess this function is a little bit over my head...
While Captaintokyo's method is accurate, it's also fairly slow. I can't help but think it'd be more advantageous to use a temporary table of all zipcodes whose boundaries are within the range, then to refine those results by distance.