在我的网站上,我正试图在附近找到位置。
我正在尝试使用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]:未定义的函数:7错误:函数弧度(文本)不存在第1行:... id,(6371 * acos(cos) (弧度(51.8391))* cos(弧度(l ... ^ HINT:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。在......
或许它与我必须在我的查询中更改文本lat
有关。但我不知道应该是什么。
51.8391和4.6265是我的“起点”的长点。
我非常感谢任何帮助,因为我不知道该改变什么: - )
修改
看起来问题出在我尝试的地方:radians(lat)
。
lat是我表格中的一列。
当我尝试使用rad()
作为hakre建议错误更改为:function rad(numeric) does not exist
编辑2
现在我们到了某个地方。
确实设置为文本的列的数据类型(由mu建议的太短)。
我把它改为双精度。
但是现在又出现了另一个错误:
警告:PDOStatement :: execute()[pdostatement.execute]:SQLSTATE [42703]:未定义列:7错误:列“距离”不存在第1行:... adians(lat))))AS距离来自距离<... ^的商店......
但我以为我在选择中做了一个别名。有什么想法吗?
另外,如果你们认为这应该是另一个问题,请告诉我,我会关闭这个。
答案 0 :(得分:7)
PostgreSQL确实有radians
函数:
radians(dp)
度数到弧度
但是radians
想要一个浮点参数,你试图给它一些字符串:
未定义的功能:7错误:函数弧度(文本)
[...]提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。
强调我的。显然,您的lat
和lng
列是char(n)
,varchar(n)
或text
列。您应该将lat
和lng
的列类型固定为numeric
,float
或其他floating point type;与此同时,您可以手动cast your strings并希望您没有任何损坏的数据:
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
答案 1 :(得分:2)
转换为弧度非常简单:
radians(n) = n * PI / 180.0