查询 MySQL 给定英里半径内的纬度和经度坐标
Querying MySQL for latitude and longitude coordinates that are within a given mile radius
我目前有一个 MySQL table 结构如下:
id name lon lat
----- ----- ----------- -----------
1 Mark -76.316528 40.036027
2 John -95.995102 41.25716
3 Paul -82.337036 29.645095
4 Dave -82.337036 29.645095
5 Chris -76.316528 40.036027
我目前查询数据库以查看用户位置是否在给定位置的特定英里半径内的方法是这样做的。
function Haversine($lat_from, $lon_from, $lat_to, $lon_to) {
$radius = 6371000;
$delta_lat = deg2rad($lat_to-$lat_from);
$delta_lon = deg2rad($lon_to-$lon_from);
$a = sin($delta_lat/2) * sin($delta_lat/2) +
cos(deg2rad($lat_from)) * cos(deg2rad($lat_to)) *
sin($delta_lon/2) * sin($delta_lon/2);
$c = 2*atan2(sqrt($a), sqrt(1-$a));
// Convert the distance from meters to miles
return ceil(($radius*$c)*0.000621371);
}
// Set the given location to NYC
$my_lon = -73.9844;
$my_lat = 40.7590;
// Query the DB for all of the users
$sql = "SELECT * FROM users";
$result = mysqli_query($con, $sql)or die(mysqli_error($con));
$count = mysqli_num_rows($result);
$i = 0;
while($row = mysqli_fetch_assoc($result)) {
$lon[$i] = $row['lon'];
$lat[$i] = $row['lat'];
$i++;
}
for($i=0;$i<$count;$i++) {
// Calculate the distance between each user's location and my location
$distance = Haversine($my_lat, $my_lon, $lat[$i], $lon[$i);
if($distance < 50) {
echo "Close enough";
}
}
这适用于 table 中只有几百行的情况。但是,现在我有几万行,检查这么多行被证明是非常耗时的。我想知道是否有一种方法可以使用 Haversine 公式来仅查询 50 英里半径范围内的行。
余弦球面定律公式
(37和-122是你半径中心的经纬度)
SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) )
* cos( radians( long ) - radians(-122) ) + sin( radians(37) ) * sin(radians(lat)) ) ) AS distance
FROM myTable
HAVING distance < 50
ORDER BY distance
特点
- 最快
- 精度类似于 Harvesine 公式
Haversine 公式
SELECT id, 3959 * 2 * ASIN(SQRT(POWER(SIN((37 - abs(lat)) * pi()/180 / 2), 2)
+ COS(37 * pi()/180 ) * COS(abs(lat) * pi()/180)
* POWER(SIN((-122 - long) * pi()/180 / 2), 2) )) as distance
FROM myTable
HAVING distance < 50
ORDER BY distance
特点
- 快
- 对浮点错误更稳健
请注意,3959 是以英里为单位的地球半径。地球半径(千米):6371
您可以找到更多信息here
我目前有一个 MySQL table 结构如下:
id name lon lat
----- ----- ----------- -----------
1 Mark -76.316528 40.036027
2 John -95.995102 41.25716
3 Paul -82.337036 29.645095
4 Dave -82.337036 29.645095
5 Chris -76.316528 40.036027
我目前查询数据库以查看用户位置是否在给定位置的特定英里半径内的方法是这样做的。
function Haversine($lat_from, $lon_from, $lat_to, $lon_to) {
$radius = 6371000;
$delta_lat = deg2rad($lat_to-$lat_from);
$delta_lon = deg2rad($lon_to-$lon_from);
$a = sin($delta_lat/2) * sin($delta_lat/2) +
cos(deg2rad($lat_from)) * cos(deg2rad($lat_to)) *
sin($delta_lon/2) * sin($delta_lon/2);
$c = 2*atan2(sqrt($a), sqrt(1-$a));
// Convert the distance from meters to miles
return ceil(($radius*$c)*0.000621371);
}
// Set the given location to NYC
$my_lon = -73.9844;
$my_lat = 40.7590;
// Query the DB for all of the users
$sql = "SELECT * FROM users";
$result = mysqli_query($con, $sql)or die(mysqli_error($con));
$count = mysqli_num_rows($result);
$i = 0;
while($row = mysqli_fetch_assoc($result)) {
$lon[$i] = $row['lon'];
$lat[$i] = $row['lat'];
$i++;
}
for($i=0;$i<$count;$i++) {
// Calculate the distance between each user's location and my location
$distance = Haversine($my_lat, $my_lon, $lat[$i], $lon[$i);
if($distance < 50) {
echo "Close enough";
}
}
这适用于 table 中只有几百行的情况。但是,现在我有几万行,检查这么多行被证明是非常耗时的。我想知道是否有一种方法可以使用 Haversine 公式来仅查询 50 英里半径范围内的行。
余弦球面定律公式
(37和-122是你半径中心的经纬度)
SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) )
* cos( radians( long ) - radians(-122) ) + sin( radians(37) ) * sin(radians(lat)) ) ) AS distance
FROM myTable
HAVING distance < 50
ORDER BY distance
特点
- 最快
- 精度类似于 Harvesine 公式
Haversine 公式
SELECT id, 3959 * 2 * ASIN(SQRT(POWER(SIN((37 - abs(lat)) * pi()/180 / 2), 2)
+ COS(37 * pi()/180 ) * COS(abs(lat) * pi()/180)
* POWER(SIN((-122 - long) * pi()/180 / 2), 2) )) as distance
FROM myTable
HAVING distance < 50
ORDER BY distance
特点
- 快
- 对浮点错误更稳健
请注意,3959 是以英里为单位的地球半径。地球半径(千米):6371
您可以找到更多信息here