Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 将Haversine公式与PostgreSQL和PDO结合使用_Php_Postgresql_Pdo_Haversine - Fatal编程技术网

Php 将Haversine公式与PostgreSQL和PDO结合使用

Php 将Haversine公式与PostgreSQL和PDO结合使用,php,postgresql,pdo,haversine,Php,Postgresql,Pdo,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

在我的网站上,我试图找到附近的位置

我试着用哈弗森公式

我使用下面的查询来获取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
选择id,(6371*acos(弧度(51.8391))*cos(弧度(纬度))*cos(弧度(lng)-弧度(4.6265))+sin(弧度(51.8391))*sin(弧度(纬度)))作为距离
从商店
距离小于25的
按名称订购asc
但是我觉得有些函数可能只是MySQL,因为我得到以下错误:

警告:PDOStatement::execute()[PDOStatement.execute]:SQLSTATE[42883]:未定义的函数:7错误:函数弧度(文本)不存在第1行:…id,(6371*acos(cos(radians(51.8391))*cos(radians(l…^)提示:没有函数与给定的名称和参数类型匹配。您可能需要添加显式类型转换。在

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

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

非常感谢您的帮助,因为我不知道要更改什么:-)

编辑

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

lat是我表格中的一列

当我尝试使用hakre建议的
rad()
时,错误更改为:
函数rad(数值)不存在

编辑2

现在我们有进展了

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

我把它改成了双精度

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


警告:PDOStatement::execute()[PDOStatement.execute]:SQLSTATE[42703]:未定义列:7错误:列“距离”不存在(第1行:…adians(lat))),因为与具有距离转换为弧度的车间的距离很小:

radians(n) = n * PI / 180.0
PostgreSQL确实有一个功能:

弧度(dp)

度到弧度

但是,
radians
需要一个浮点参数,而您正试图给它一个某种类型的字符串:

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

我的。显然,您的
lat
lng
列是
char(n)
varchar(n)
text
列。您应该将
lat
lng
的列类型固定为
numeric
float
或其他类型;同时,您可以手动操作,希望没有任何损坏的数据:

radians(cast(lat as double precision))
MySQL做了大量的隐式类型转换,PostgreSQL更为严格,要求您准确地说出自己的意思


第二个问题的更新:在
SELECT
子句之前对
HAVING
子句进行求值,因此
SELECT
中的列别名通常在查询的其他任何位置都不可用。你有两个选择,你可以重复你丑陋的哈弗森:

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
选择id,(6371*acos(弧度(51.8391))*cos(弧度(纬度))*cos(弧度(lng)-弧度(4.6265))+sin(弧度(51.8391))*sin(弧度(纬度)))作为距离
从商店
具有(6371*acos(cos(弧度(51.8391))*cos(弧度(lat))*cos(弧度(lng)-弧度(4.6265))+sin(弧度(51.8391))*sin(弧度(lat))<25
按名称订购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
选择id、距离
从(
选择id、名称,(6371*acos(cos(弧度(51.8391))*cos(弧度(纬度))*cos(弧度(lng)-弧度(4.6265))+sin(弧度(51.8391))*sin(弧度(纬度)))作为距离
从商店
)as dt
其中距离<25.0
按名称订购asc

@hakre:nopez没有运气。请参见editWas仅是一个快速快照(很抱歉,它不起作用:)),请参见如何在postgresql中定义函数,以便您可以更轻松(更快)地将其应用于查询中(请参见)。注意:这不是Haversine公式-这是更简单的基于余弦的公式。Haversine要复杂得多,但更精确,除非使用高精度(例如双精度)算法。我个人认为新位应该是一个单独的问题,但这里已经有很多关于“有vs在哪里”的问题,这可能与列(-data)有关吗?因为我认为这是需要做的。但不确定。。。另请参见我的editPostgreSQL有一个
radians
函数,问题是
lat
lng
不是数字。当然-只需在数据库中存储弧度数据,而不是度。更好的是,看看这个答案:就像@mu所说的那样——将数字存储为数字,而不是文本@阿尔尼塔克:是的,是的,那只是我的愚蠢:)太好了。看来这确实是个问题。不过,我现在又犯了一个错误:(感谢您迄今为止的帮助!如果您愿意,或者如果您不想,请编辑这个问题。)非常感谢!我将使用第一个选项,因为公式已经在变量中。工作:2*6371*asin(sqrt((sin(弧度((lat2-lat1)/2))^2+cos(弧度(lat1))*cos(弧度(lat2))*(sin(弧度((lon2-lon1)/2))^2))