5

在我的网站上,我正在尝试获取附近的位置。

我正在尝试为此使用Haversine 公式。

我正在使用以下查询来获取 25 公里半径内的所有位置。

SELECT id, ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) AS distance
FROM shops
HAVING distance < 25
ORDER BY name asc

但是我认为某些功能可能只是 MySQL,因为我收到以下错误:

警告:PDOStatement::execute() [pdostatement.execute]: SQLSTATE[42883]: Undefined function: 7 ERROR: function radians(text) does not exist LINE 1: ...id, ( 6371 * acos( cos( radians( 51.8391) ) * cos( radians( l... ^ 提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。在 ...

或者也许这与我必须更改lat查询中的文本有关。但我不知道它应该是什么。

51.8391 和 4.6265 是我的“起点”点的经纬度。

非常感谢任何帮助,因为我不知道要改变什么:-)

编辑

看起来问题出在我尝试做的地方:radians(lat).

lat 是我表中的一列。

当我尝试使用rad()hakre 建议时,错误更改为:function rad(numeric) does not exist

编辑 2

现在我们正在取得进展。

确实设置为文本的列的数据类型(如 mu 所建议的那样太短)。

我已将其更改为双精度。

但是现在我得到另一个错误:

警告:PDOStatement::execute() [pdostatement.execute]: SQLSTATE[42703]: Undefined column: 7 ERROR: column "distance" does not exist LINE 1: ...adians( lat ) ) ) AS distance from stores HAVING距离 <... ^ 在 ...

但我以为我在选择中做了一个别名。有任何想法吗?

另外,如果你们认为这应该进入另一个问题,请告诉我,我会关闭这个问题。

4

2 回答 2

8

PostgreSQL 确实有一个radians功能:

radians(dp)
度数到弧度

但是radians想要一个浮点参数,并且您正试图给它某种字符串:

未定义函数:7 错误:函数弧度(文本
[...] 提示:没有函数与给定名称和参数类型匹配。您可能需要添加显式类型转换

强调我的。显然,您的latlng列是char(n)varchar(n)text列。您应该将列类型固定为,lat或其他浮点类型;同时,您可以手动转换字符串,并希望您没有任何损坏的数据:lngnumericfloat

radians(cast(lat as double precision))

MySQL 做了很多隐式类型转换,PostgreSQL 更严格,要求你准确地说出你的意思。


第二个问题的更新HAVING子句在子句之前进行评估,因此在查询中的其他任何地方通常不可用SELECT列别名。SELECT你有几个选择,你可以重复你的大丑Haversine:

SELECT id, ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) AS distance
FROM shops
HAVING ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) < 25
ORDER BY name asc

或者使用派生表来避免重复自己:

select id, distance
from (
    select id, name, ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) as distance
    from shops
) as dt
where distance < 25.0
order by name asc
于 2011-08-07T20:58:02.830 回答
2

转换为弧度很简单:

radians(n) = n * PI / 180.0
于 2011-08-07T20:48:27.433 回答