在我的网站上,我试图找到附近的位置。
我正在尝试使用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,因为出现以下错误:
或者也许与事实有关,我必须在查询中更改文本
lat
。但是我不知道该怎么办。51.8391和4.6265是我“起点”的漫长和滞后。
非常感谢您的帮助,因为我不知道该如何更改:-)
编辑
看来问题出在我想做的地方:
radians(lat)
。lat是我表中的一列。
当我尝试使用
rad()
作为hakre建议时,错误更改为:function rad(numeric) does not exist
编辑2
现在我们到了某个地方。
实际上设置为文本的列的数据类型(如mu所建议的太短)。
我已将其更改为 double 。
但是现在我得到另一个错误:
但是我以为我在选择中做了一个别名。有任何想法吗?
另外,如果你们认为这应该引起另一个问题,请告诉我,我将结束这个问题。
最佳答案
PostgreSQL确实有一个 radians
函数:
但是radians
需要一个浮点参数,而您试图给它一个某种形式的字符串:
强调我的。显然,您的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
关于php - 将Haversine公式与PostgreSQL和PDO一起使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6975669/