3

我有闲置的 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'?

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

4

4 回答 4

4

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

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

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

沿着球体表面的距离有一个更好的公式,称为文森蒂公式。它的最后一个操作是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 中的三角函数(余弦、正弦、反正切等)是使用服务器计算机的浮点数学子系统实现的。如果您以 DECIMAL 格式向他们提供数据,则数据将转换为 DOUBLE、计算,然后再转换回来。这将导致它失去精度。数据类型(FLOATIEEE-488 单精度浮点)为商业 GPS 风格的纬度和经度数据提供了足够的准确性。

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

于 2014-05-05T02:06:13.547 回答
1

它不应该返回空值。您有左连接而不是内连接,因此您的表中可能有一些记录,而 tbl_country_de 中没有匹配的管理代码

还是您的数据中有空值?

于 2013-07-30T17:51:21.693 回答
0

我已将纬度和经度数据类型从十进制(10,7)更改为浮点(10,7)并且它可以工作。不知道这是不是真正的问题??

于 2013-07-30T18:26:44.243 回答
0

我知道这是一个非常古老的线程,但我只是在一些遗留代码中遇到了这个问题。我通过在距离计算周围使用合并函数解决了这个问题。

select coalesce(*distance caclulation*, 0) as distance from ...

因此,我从计算中得到 0 而不是 null。我相信有人会告诉我这是一种骇人听闻的、可怕的方法,但这对我们来说也不是关键操作,否则有人会在此之前发现错误。

于 2016-07-08T19:37:25.470 回答