2012-11-21 87 views
3

我已经在网上搜索了很多,以找到解决我的问题,但我仍然无法弄清楚。使用经度和纬度查找使用MySQL最接近的10个城市?

我有一个非常简单的数据库ID,城市名称,纬度,经度和city_info。当有人进入城市页面时,想要显示附近的10个城市。

我怎样才能计算这与MySQL并返回与PHP?

我在这个网站上看到了很多建议,但是这些工作都不知道。

我试过没有成功。我没有得到任何结果。

<?php 
$slatitude = 43.2141341; 
$slongitude = 64.4368684; 
$miles = 200; 

//connect 

$query = "SELECT *, 
(3959 * acos(cos(radians('$slatitude')) * 
cos(radians(latitude)) * 
cos(radians(longitude) - 
radians('$slongitude')) + 
sin(radians('$slatitude')) * 
sin(radians(latitude)))) 
AS distance FROM cities HAVING distance < '$miles' ORDER BY distance ASC LIMIT 0, 10"; 

$query = mysql_query($query); 
$numrows = mysql_num_rows($query); 
if ($numrows > 0){ 

while ($row = mysql_fetch_assoc($query)){ 
$id = $row['id']; 
$cityname = $row['cityname']; 
$latitude = $row['latitude']; 
$longitude = $row['longitude']; 

echo "$cityname<br />"; 

}} 

?>` 
+0

您是否*在您的数据库中有200英里以内的城市? – BenOfTheNorth

+0

你没有'HAVING'子句的结果吗?你有错误信息吗? –

+0

我的数据库里绝对有200英里以内的城市。我根本没有得到任何错误。 –

回答

2

你不能使用因为你没有任何分组。你需要做的是重复你在选择的地方做了什么。

$query = "SELECT *, 
(3959 * acos(cos(radians('$slatitude')) * 
cos(radians(latitude)) * 
cos(radians(longitude) - 
radians('$slongitude')) + 
sin(radians('$slatitude')) * 
sin(radians(latitude)))) 
AS distance FROM cities WHERE (3959 * acos(cos(radians('$slatitude')) * 
cos(radians(latitude)) * 
cos(radians(longitude) - 
radians('$slongitude')) + 
sin(radians('$slatitude')) * 
sin(radians(latitude)))) < '$miles' ORDER BY distance ASC LIMIT 0, 10"; 

,或者你可以做这样的事情:

$query = " 
SELECT * FROM (
    select *, 
    (3959 * acos(cos(radians('$slatitude')) * 
    cos(radians(latitude)) * 
    cos(radians(longitude) - 
    radians('$slongitude')) + 
    sin(radians('$slatitude')) * 
    sin(radians(latitude)))) as distance from cities 
) WHERE distance < '$miles' ORDER BY distance ASC LIMIT 0, 10"; 
+1

您需要将第二个查询中的“AS距离”移到子查询中。 –

+0

是的,谢谢。我发布后发现了这一点。 –

+0

我相信这个查询会像最初使用'HAVING'子句写的那样工作。在MySQL中没有'GROUP BY'的'HAVING'子句中可以使用别名表达式,但它不是标准的SQL。 –

0

远最容易的解决办法是:

得到的坐标为城市和

select ... 
order by abs(`Latt`-reqLatt) * abs(`Long`-reqLong) 

它不是没有完美的,但你可以理清你想要的排名前50位。

+0

一般来说,但它不使用投影,所以一些错误将显示在靠近半径边缘的城市以及具有相似距离的城市的排序中。 “半径”也是“正方形”。 –

+0

这也不能提供限制200英里的方法。 –

+0

是的,你是对的。好主意 - 以下... – Teson

0

我用PDO这个作为mysql_职能被弃用

<?php 
//Connect to database 
$dbh = new PDO("mysql:host=$host;dbname=$database", $username, $password);//Change to suit 
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
try { 
    // Prepare statement 
    $stmt = $dbh->prepare("SELECT *, (3959 * acos(cos(radians(?)) * cos(radians(lat)) * cos(radians(lng) - radians(?)) + sin(radians(?)) * sin(radians(lat)))) AS distance FROM cities HAVING distance < ? ORDER BY distance LIMIT 0 , 10"); 
    // Assign parameters 
    $stmt->bindParam(1,$slatitude); 
    $stmt->bindParam(2,$slongitude); 
    $stmt->bindParam(3,$slatitude); 
    $stmt->bindParam(4,$miles); 
    //Execute query 
    $stmt->setFetchMode(PDO::FETCH_ASSOC); 
    $stmt->execute(); 
    if ($stmt->rowCount()>0) { 
    // Iterate through the rows 
    while($row = $stmt->fetch()) { 
     $id = $row['id']; 
     $cityname = $row['cityname']; 
     $latitude = $row['latitude']; 
     $longitude = $row['longitude']; 
     echo "$cityname<br />";]); 
     } 
    } 
    else{ 
     echo "No Records"; 
     } 
} 

catch(PDOException $e) { 
    echo "I'm sorry I'm afraid you can't do that.". $e->getMessage() ;// Remove or modify after testing 
    file_put_contents('PDOErrors.txt',date('[Y-m-d H:i:s]').", mapSelect.php, ". $e->getMessage()."\r\n", FILE_APPEND); 
} 
//Close the connection 
$dbh = null; 
?> 

DEMO使用该查询

2

要提高查询的速度,你可以首先限制的结果集,你会做计算使用类似下面的子选择(请注意,我还使用了不同的方法计算距离 - 它适用于我,ymmv)。 在我的测试中,使用容差为1的where子句比没有它的查询快100倍以上。

... 
$tol = 1; // limits the search to lat/long within 1 from the given values 
$query_args = array($lat,$long,$lat-$tol,$lat+$tol,$long-$tol,$long+$tol); 
$query = " 
    SELECT *,latitude, longitude, 
    SQRT(POW(69.1 * (latitude - %s) , 2) 
     + POW(69.1 * (%s - longitude) 
      * COS(latitude/57.3) , 2)) 
    AS distance FROM zipcodes 
     WHERE latitude > %d AND latitude < %d 
     AND longitude > %d AND longitude < %d 
    ORDER BY distance ASC limit 10 
"; 
... 
1

下面是我用来从给定经度/纬度集合中获得最接近的邮政编码的查询。该表是非常简单的:

ID,邮编,纬度,经度

此查询假设你的中心点是用 “$ slatitude:和:$ slongitude”。这将返回距离变量“$英里”(即3,2.4,1000)内的所有匹配。在我的脚本中,结果放入一个数组,并为最接近X的结果分类。

$getzip = mysql_query("SELECT zip,((ACOS(SIN(".$slatitude." * PI()/180) * SIN(lat * PI()/180) + COS(".$slatitude." * PI()/180) * COS(lat * PI()/180) * COS((".$slongitude." - lng) * PI()/180)) * 180/PI()) * 60 * 1.1515) AS distance FROM zips HAVING distance<='$miles' ORDER BY 'distance' ASC", $link2) or die (mysql_error($link2)); 

希望它有帮助!

相关问题