php - MYSQL无法选取点间距离(lat,lng)=0的记录

标签 php mysql floating-point latitude-longitude trigonometry

我有一个休闲的 mysql 查询

SELECT de.geoId,(6371 * ACOS( COS( RADIANS(zde.latitude) )* 
    COS(RADIANS( de.latitude ) ) * COS( RADIANS( de.longitude ) - RADIANS(zde.longitude) ) + 
    SIN( RADIANS(zde.latitude) ) * SIN( RADIANS( de.latitude ) ) ) )  AS distance 
FROM tbl_zipde AS zde 
    LEFT JOIN  tbl_country_de AS de 
             ON (de.admin1_code=zde.admin_code1)  
                 Where zde.id=8 and  de.geoId=24 having distance<1

此查询应从表 tbl_zountry_de 返回一条记录,该记录与 tbl_zipde 中 id=8 的记录具有相同的纬度和经度值,但因为计算出的这两点之间的距离为 0,mysql 将 0 识别为 NULL 距离,因此它不返回任何记录,但如果我删除“有距离<1”,那么它会从 tbl_country_de 返回 id=24 的核心记录,但表列距离为 NULL 值。

我应该如何编写 mysql 查询,以便 mysql 返回两点(纬度和经度值)之间的距离等于 0 的记录

为什么 mysql 对距离返回 NULL 而不是 '0'?

我已将纬度和经度数据类型从 decimal(10,7) 更改为 float(10,7),并且可以正常工作。 不知道这是否是真正的问题??

最佳答案

这个问题已经存在一段时间了,但是还没有得到正确的回答。

DECIMAL 是不适合地理定位数据的数据类型。

问题中的公式称为球面余弦定律公式。如果您仔细查看此公式,您会注意到,当您处理非常接近的点时,它会取一个非常接近 1 的数字的反余弦 (ACOS())。这是一个数值不稳定的操作。 Unstable 在这种情况下意味着如果输入中有小的错误,函数的输出可能会有很大差异。

有一个更好的球体表面距离公式,称为文森蒂公式。它的最后一个操作是 ATAN2():对于小角度,这是一个数值上更稳定的操作。就是这样:

111.045 * DEGREES(ATAN2(SQRT(
    POW(COS(RADIANS(lat2))*SIN(RADIANS(lon2-lon1)),2) +
    POW(COS(RADIANS(lat1))*SIN(RADIANS(lat2)) -
         (SIN(RADIANS(lat1))*COS(RADIANS(lat2)) *
          COS(RADIANS(lon2-lon1))) ,2)),
  SIN(RADIANS(lat1))*SIN(RADIANS(lat2)) +
  COS(RADIANS(lat1))*COS(RADIANS(lat2))*COS(RADIANS(lon2-lon1))))

这里有一个 MySQL 存储过程:http://www.plumislandmedia.net/mysql/vicenty-great-circle-distance-formula/

您可以在这里查找数学:http://en.wikipedia.org/wiki/Great-circle_distance

此外,请记住 MySQL 中的三角函数(余弦、正弦、反正切等)是使用服务器计算机的 float 学子系统实现的。如果您以 DECIMAL 格式向他们提供数据,则数据将转换为 DOUBLE、计算,然后再转换回来。这将导致它失去精度。 FLOAT 数据类型(IEEE-488 单精度浮点)为商业 GPS 样式的纬度和经度数据提供了足够的精度。

问题中提到的 NULL 结果可能是由于在 DOUBLE 和 DECIMAL 之间转换时固有的错误导致 ACOS 的输入无限大于 1。 1.00001 的反余弦运算失败并产生 NULL。切换到 FLOAT 和 Vincenty 公式将消除这个故障源。

关于php - MYSQL无法选取点间距离(lat,lng)=0的记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17953766/

相关文章:

mysql - PrestaShopDatabaseException MySQL 服务器在迁移到 VPS 后消失了

mysql - 类似类对象推荐的 MySQL 数据模型

c - 从捕获浮点异常返回

javascript - 我正在学习 php 和 mysql,我正在使用数组创建动态表单。抛出空查询警告

php - 在 HTTP header 中设置到期日期或最长期限

如果条件满足,PHP mysql更新并插入

php - 获取所有子类别的递归函数

php - 如何将 MySQL 数据库文件 (.sql) 转换为 PHP 中的 SQLite 文件?

c - float 和 double 数据类型在 gcc 编译器中工作吗?

c++ - 如何对 float 执行按位运算