2010-10-25 57 views
2

注意:尽管我使用荷兰邮政编码的邮政编码数据库,但这个问题与国家无关。mySQL在y范围内选择x公里/英里内的邮政编码

我有一个数据库,每个邮政编码在荷兰+其x和y坐标(纬度/经度)。

我有例如邮编:$baseZipCode = 1044;具有以下坐标:

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

现在,我想从$baseZipCode找到所有其他与邮编$range

例如:

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

的问题是,地球是不是完整的圆形。我找到了很多带有from a to b计算的教程,但那不是我所需要的。

有没有人有任何想法?


UPDATE 感谢Captaintokyo我发现这一点:

想找到从另一个邮政编码或点一定英里/公里半径范围内的所有邮编和相应的距离是多少?这个问题需要经纬度坐标来解决。对地址进行地理编码可以为您提供地址的纬度/经度坐标。

首先,你需要的所有邮编的数据库及其相应的纬度和经度坐标:

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`) 
) 

所以一旦你有你想找到一个中心点的某些英里半径范围内的所有邮编数据库。如果中心点是另一个邮政编码,只需查询该邮政编码的纬度和经度坐标数据库。然后代码如下:

// 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"; 

} 

(雅虎和谷歌提供免费的地理编码服务。)

回答

0

你想要做这样的事情:

SELECT zipcode FROM zipcodes WHERE DistanceFormula(lat, long, 4.808855, 52.406332) < $range

它可能会很慢如果你的邮政编码表很大。您可能还想查看MySQL的地理空间扩展。

4

你必须使用一种叫做Haversine formula

$sql = " 
    SELECT zipcode 
    FROM zipcodes 
    WHERE ".mysqlHaversine($lat, $lon, $distance)." 
"; 

和公式:

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 ''; 
} 

通常我不会不理解它的工作原理第一方式使用代码,但我必须承认这功能有点超过我的头...

+0

你对关于haversine配方的评论帮了我很多。但是,您的查询与我找到的不一样。我用正确的查询更新了我的主题。 – 2010-10-25 07:05:13

+3

听起来像您在暗示我的回答不正确。只是想指出它完全适用于我的应用程序。祝贺您找到了可以做同样事情的不同功能。 – Mischa 2010-10-26 03:41:22

+1

这里的距离单位是多少? – 2016-07-30 07:34:11

2

虽然Captaintokyo的方法是准确的,但它也相当缓慢。我不禁想到,使用边界在范围内的所有邮编的临时表格,然后按距离细化这些结果会更有优势。

相关问题