2010-10-25 62 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的方法是準確的,但它也相當緩慢。我不禁想到,使用邊界在範圍內的所有郵編的臨時表格,然後按距離細化這些結果會更有優勢。

相關問題