【问题标题】:MySQL geospacial search using haversine formula returns null on same pointMySQL地理空间搜索使用haversine公式在同一点返回null
【发布时间】:2015-03-31 01:10:09
【问题描述】:

我正在尝试在 php 应用程序中实现地理空间搜索。目前,我正在使用以下查询来查找给定纬度和经度 10 公里内的点:

SELECT * FROM (
      SELECT *,
             (6378.1 * ACOS(
                  COS(RADIANS(48.856614)) * COS(RADIANS(latitude))
                * COS(RADIANS(2.3522219) - RADIANS(longitude))
                + SIN(RADIANS(48.856614))
                * SIN(RADIANS(latitude)))
             ) AS distance
      FROM `destinations_info`
      WHERE latitude BETWEEN 48.856614  - (10 / 69)
               AND 48.856614  + (10 / 69)
        AND longitude BETWEEN 2.3522219 - (10 / (69 * COS(RADIANS(48.856614))))
               AND 2.3522219 + (10 / (69 * COS(RADIANS(48.856614))))
      ) d
WHERE distance <= 10
LIMIT 1

只要我不搜索存储在 POI 表中的确切纬度和经度,此方法就可以正常工作。

例如,如果我的 poi 表中有以下条目

id     name     latitude    longitude
1      Paris    48.856614   2.3522219000000177

我用lat = 48.856614long = 2.3522219000000177 调用查询我不会得到任何结果。据我所知,这是因为以下操作在 mysql 中返回 NULL 而不是 0:

SELECT (6378.1 * acos(cos(radians(48.856614)) * cos(radians(48.856614)) * cos( radians(2.3522219) - radians(2.3522219)) + sin(radians(48.856614)) * sin(radians(48.856614)))) 

在 Chrome 计算器I get 0 rad 中运行相同的操作。

查询中是否有问题,或者我是否还需要使用“OR IS NULL”来包含 NULL 结果

【问题讨论】:

    标签: php mysql haversine


    【解决方案1】:

    IFNULL( ... ),0) AS Distance 也将帮助您绕过错误。

    【讨论】:

    • +1 - 当查询中指定的纬度/经度与我要检索的数据库中记录的经度/经度完全匹配时,我遇到了这个问题。好的,优雅的解决方案。
    【解决方案2】:

    问题是acos被调用的值不在-1和1的范围内,所以它返回null。

    SELECT cos(radians(48.856614)) * cos(radians(48.856614)) * cos( radians(2.3522219) - radians(2.3522219)) + sin(radians(48.856614)) * sin(radians(48.856614))
    
    1.0000000000000002
    

    这似乎是某种四舍五入的问题。

    由于 arc cos 只定义在 -1 和 1 之间,您可能应该预先检查它的参数,或者准备好在计算出现问题时它可以返回 null。

    【讨论】:

    • 我现在注意到我的纬度、经度列是 varchar 255 类型,所以不是浮点数,因此它允许在小数点后存储超过 8 个数字。将类型更改为浮动,现在它可以工作,但我真的不知道它有多安全/准确。
    • 存储在 varchar 中的值被转换,所以这不是问题。直到您不需要比较浮点值,我认为这很好。但请注意,它并不能解决 acos 可能返回 null 的问题。机会非常低,但您的示例中已经有一个。所以同样的事情会再次发生。
    猜你喜欢
    • 2014-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多