我有一个表(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或DESC)对数组进行排序。我应该如何调整我的查询,以便发生这种情况?
提前感谢。
更新:"距离"这个词可能显得模棱两可(多亏了豪尔赫)。我只是希望按距离(即两点之间的距离)对zip_codes进行排序。
你可以用
$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值。
ORDER BY (3958*3.1415926*sqrt((lat-$lat)*(lat-$lat) + cos(lat/57.29578)*cos($lat/57.29578)*(lon-$lon)*(lon-$lon))/180) DESC
MySQL有几何函数来计算距离。但是,您需要将坐标对管理为Point
字段,而不是单独的float字段。一种解决方法是将两个列转换为一个坐标对。
$sql = "SELECT userID,
city,
zip_code,
country,
GeometryFromText( CONCAT( 'POINT(', lon, ' ', lat, ')' ) ) as coord
FROM user_zip_codes ";
如果您使用$lat和$lon变量来强制转换LineString
而不是点数,则可以使用GLength
来获得距离
$sql = "SELECT userID,
city,
zip_code,
country,
GLength(GeomFromText(CONCAT('LineString(',lon,' ', lat1,',$lon $lat)'))) as distance
FROM user_zip_codes
where GLength(GeomFromText(CONCAT('LineString(',lon,' ', lat1,',$lon $lat)')))<=$radius
ORDER BY distance DESC";
看起来还是很乱。应该有一种不使用其WKT表示来声明LineString的方法。我会继续找的。