按距离排序邮政编码邻近搜索(php / mysql)

时间:2014-07-14 11:52:10

标签: php mysql

我有一个表(user_zip_codes),其中包含用户的zip_code,纬度和经度。我在stackoverflow上找到了一个函数,它找到特定半径内的邮政编码:

function zipcodeRadius($lat, $lon, $radius) {
    global $mysqli;
    $zipcodeList = array();
    $radius = ($radius ? $radius : 20);
    $sql = "SELECT userID,city,zip_code,country FROM user_zip_codes  WHERE (3958*3.1415926*sqrt((lat-$lat)*(lat-$lat) + cos(lat/57.29578)*cos($lat/57.29578)*(lon-$lon)*(lon-$lon))/180) <= $radius GROUP BY zip_code";
    if($stmt = $mysqli->prepare($sql)) {
        $stmt->execute();
        $stmt->bind_result($userID,$city,$zip_code,$country);
        while($stmt->fetch()) {
            $zipcodeList[] = array('userID'=>$userID,'city'=>$city,'zip_code'=>$zip_code,'country'=>$country);
        }
    }
    return $zipcodeList;
}

完美无缺。但是,我希望函数按距离对数组进行排序(通过ASC og DESC)。我应该如何调整我的查询才能实现此目的?

提前致谢。

更新 “距离”这个词可能看起来含糊不清(感谢Jorge)。我只想按照距离对zip_codes进行排序,即两点之间的距离。

3 个答案:

答案 0 :(得分:4)

您可以使用类似

的内容
$iDistance = 20;
$iRadius = 6371; // earth radius in km
$iRadius = 3958; // earth radius in miles
$fLat = x.y; // Your position latitude
$fLon = x.y; // Your position longitude

$strQuery = "
SELECT 
  *, 
  $iRadius * 2 * ASIN(SQRT(POWER(SIN(( $fLat - abs(pos.lat)) * pi() / 180 / 2),2) +
COS( $fLat * pi()/180) * COS(abs(pos.lat) * pi() / 180) * POWER(SIN(( $fLon - pos.lon) *
pi() / 180 / 2), 2) )) AS distance
FROM user_zip_codes pos
HAVING distance < $iDistance 
ORDER BY distance";

在使用SQL之前必须获取lat / lon值。这对我有用

答案 1 :(得分:0)

ORDER BY (3958*3.1415926*sqrt((lat-$lat)*(lat-$lat) + cos(lat/57.29578)*cos($lat/57.29578)*(lon-$lon)*(lon-$lon))/180) DESC

答案 2 :(得分:0)

MySQL具有计算距离的几何函数。但是,您需要将坐标对作为Point字段而不是单独的浮点字段进行管理。解决方法是将两列都转换为坐标对。

$sql = "SELECT userID,
            city,
            zip_code,
            country, 
            GeometryFromText( CONCAT( 'POINT(', lon, ' ', lat, ')' ) ) as coord
        FROM user_zip_codes  ";

如果您使用$ lat和$ lon变量来投射{​​{1}}而不是积分,则可以使用LineString来获取距离

GLength

它看起来仍然很混乱。应该有一种方法来声明一个LineString而不使用它的WKT表示。我一直在寻找。