将Haversine公式与PHP PDO结合使用

时间:2013-06-13 05:15:11

标签: php mysql pdo geo haversine

最初使用以下查询:

SELECT username, latitude, longitude, ( 3959 * acos( cos( radians(':lat') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(':lng') ) + sin( radians(':lat') ) * sin( radians( latitude ) ) ) ) AS distance FROM users HAVING distance < '500' ORDER BY distance LIMIT 0 , 20

当我在控制台中运行它(用我的实际数字替换我的PDO占位符(:lat,:lng等))时这很有效但是只要我通过PHP-PDO运行它,即:

$stmt = db::getInstance()->prepare($sql);
 $stmt->bindParam(':lat', $lat, PDO::PARAM_STR);
 $stmt->bindParam(':lng', $lng, PDO::PARAM_STR);
 $stmt->bindParam(':radius', $radius, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchAll();

它有问题并且什么都不返回 问题是PDO处理HAVING的方式与原始查询不同,显然

所以没关系,我已经重写了替换HAVING的查询,新查询看起来像这样:

SELECT * FROM ( SELECT username, latitude, longitude, ( 3959 * acos( cos( radians(':lat') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(':lng') ) + sin( radians(':lat') ) * sin( radians( latitude ) ) ) ) ) WHERE distance < '500' ORDER BY distance LIMIT 0 , 20

这会导致PDO出现以下错误:

  带有消息'SQLSTATE [42000]的

异常'PDOException':语法错误   或访问冲突:1248每个派生表必须有自己的别名'   在   /home/bessr/local_html/site.com/pieces/functions/geo.functions.php:47   堆栈跟踪:#0   /home/bessr/local_html/site.com/pieces/functions/geo.functions.php(47):   PDOStatement-&gt; execute()#1 {main}

好吧,所以我给它一个别名,我的修改后的查询看起来像这样:

SELECT * FROM ( SELECT username, latitude, longitude, ( 3959 * acos( cos( radians(':lat') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(':lng') ) + sin( radians(':lat') ) * sin( radians( latitude ) ) ) AS t ) AS alias ) WHERE distance < '500' ORDER BY distance LIMIT 0 , 20

即使我添加了别名,我仍然会遇到同样的错误。我不确定我哪里出错了。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:0)

PDO根本不处理任何SQL。显然。

唯一的工作就是将您的查询发送到mysql服务器并获得结果。 全部处理由mysql服务器完成。

因此,您的问题就在其他地方。很可能它可能是由您连接的不同mysql版本引起的。

尽管错误必须得到解决。尝试将as alias移出大括号。

答案 1 :(得分:0)

您在查询中引用了指定的占位符。您也没有使用:radius。以下查询删除引号并添加:radius适用于我的数据库。

SELECT username, latitude, longitude,
( 3959 * acos( cos( radians(:lat) ) * cos( radians( latitude ) ) 
* cos( radians( longitude ) - radians(:lng) ) + sin( radians(:lat) )
* sin( radians( latitude ) ) ) ) AS distance FROM users
HAVING distance < :radius ORDER BY distance LIMIT 0 , 20