Search code examples
phpsqlmysqlzipcodepostal-code

mySQL select zipcodes within x km/miles within range of y


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 + its x and y coordinate (lat/long).

I have for example zipcode: $baseZipCode = 1044; with the following coordinates:

x coordinate = 4,808855
y coordinate = 52,406332

Now, I want to find all other zipcodes with $range from $baseZipCode.

For example:

SELECT
  zipcode
FROM
  zipcodes
WHERE
  ????? // Need help here

The problem is that the earth is not completely round. I find a lot of tutorials with from a to b calculations but that's not what I need.

Does anyone have any idea?


UPDATE Thanks to Captaintokyo I found this:

Want to find all zipcodes and corresponding distances within a certain mile/kilometer radius from another zipcode or point? This problems require latitude and longitude coordinates to solve. Geocoding the address gives you latitude/longitude coordinates from an address.

First you will need a database of all zipcodes and their corresponding latitude and longitude coordinates:

CREATE TABLE `zipcodes` (
  `zipcode` varchar(5) NOT NULL DEFAULT '',
  `city` varchar(100) NOT NULL DEFAULT '',
  `state` char(2) NOT NULL DEFAULT '',
  `latitude` varchar(20) NOT NULL DEFAULT '',
  `longitude` varchar(20) NOT NULL DEFAULT '',
  KEY `zipcode` (`zipcode`),
  KEY `state` (`state`)
)

So once you have the database you want to find all zipcodes within a certain mile radius of a central point. If the central point is another zipcode, simply query the database for the latitude and longitude coordinates of that zipcode. Then the code is as follows:

// ITITIAL POINT

$coords = array('latitude' => "32.8", 'longitude' => "-117.17");

//RADIUS

$radius = 30;

// SQL FOR KILOMETERS

$sql = "SELECT zipcode, ( 6371 * acos( cos( radians( {$coords['latitude']} ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians( {$coords['longitude']} ) ) + sin( radians( {$coords['latitude']} ) ) * sin( radians( latitude ) ) ) ) AS distance FROM zipcodes HAVING distance <= {$radius} ORDER BY distance";

// SQL FOR MILES

$sql = "SELECT zipcode, ( 3959 * acos( cos( radians( {$coords['latitude']} ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians( {$coords['longitude']} ) ) + sin( radians( {$coords['latitude']} ) ) * sin( radians( latitude ) ) ) ) AS distance FROM zipcodes HAVING distance <= {$radius} ORDER BY distance";

// OUTPUT THE ZIPCODES AND DISTANCES

$query = mysql_query($sql);

while($row = mysql_fetch_assoc($query)){

    echo "{$row['zipcode']} ({$row['distance']})<br>\n";

}

(Both Yahoo and Google offer free geocoding services.)


Solution

  • 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.