【问题标题】:ST_Distance_Sphere in mysql not giving accurate distance between two locationsmysql中的ST_Distance_Sphere没有给出两个位置之间的准确距离
【发布时间】:2016-06-26 16:14:18
【问题描述】:

我的requirement 是使用mysql 在给定map 上计算两个locations 之间的distance。我在mysql 中找到了一个名为ST_Distance_Sphere 的函数,它返回一个球体上两个位置和/或多个位置之间的最小球面距离(以米为单位)。

当我使用ST_Distance_Spherelat_lng_distance 函数计算两个位置之间的距离时,我发现ST_Distance_Sphere 给出的距离与lat_lng_distance 函数的距离不同。

我的lat_lng_distance功能码如下

CREATE FUNCTION `lat_lng_distance` (lat1 FLOAT, lng1 FLOAT, lat2 FLOAT, lng2 FLOAT)
RETURNS FLOAT
DETERMINISTIC
BEGIN
    RETURN 6371 * 2 * ASIN(SQRT(
        POWER(SIN((lat1 - abs(lat2)) * pi()/180 / 2),
        2) + COS(lat1 * pi()/180 ) * COS(abs(lat2) *
        pi()/180) * POWER(SIN((lng1 - lng2) *
        pi()/180 / 2), 2) ));
END

传递给ST_Distance_Spherelat_lng_distance函数的两个位置((38.898556,-77.037852),(38.897147,-77.043934))如下

SET @pt1 = ST_GeomFromText('POINT (38.898556 -77.037852)');
SET @pt2 = ST_GeomFromText('POINT (38.897147 -77.043934 )');

SELECT ST_Distance_Sphere(@pt1, @pt2)/1000,lat_lng_distance(38.898556,-77.037852,38.897147,-77.043934 );

得到的结果如下

我在google maps上查看了两个位置之间的距离,发现lat_lng_distance与两个位置之间的实际距离很接近。有人可以告诉我为什么ST_Distance_Sphere 没有给出两个位置之间的准确距离吗?

【问题讨论】:

    标签: mysql sql mysql-workbench


    【解决方案1】:

    ST_DISTANCE_SPHERE 要求将点表示为POINT(longitude, latitude),您在代码中将它们颠倒了

    set @lat1 = 38.898556;
    set @lon1 = -77.037852;
    set @lat2 = 38.897147;
    set @lon2 = -77.043934;
    SET @pt1 = point(@lon1, @lat1);
    SET @pt2 = point(@lon2, @lat2);
    SELECT ST_Distance_Sphere(@pt1, @pt2)/1000,
      lat_lng_distance(@lat1,@lon1,@lat2,@lon2);
    
    +-------------------------------------+-------------------------------------------+
    | ST_Distance_Sphere(@pt1, @pt2)/1000 | lat_lng_distance(@lat1,@lon1,@lat2,@lon2) |
    +-------------------------------------+-------------------------------------------+
    |                   0.549154584458455 |                        0.5496311783790588 |
    +-------------------------------------+-------------------------------------------+
    

    这会得到更接近函数返回值的结果。

    【讨论】:

    • 谢谢没有注意到我的错误
    【解决方案2】:

    首先,您不能使用默认的 SRID 0 来进行任何计算。当您使用文本函数中的几何图形时,您必须提供 4326(SRID 即度数),因为这是您的输入格式。 MYSQL 可能不关心它,但它应该这样做,因为每个严肃的 GIS 数据库都关心并要求指定输入 SRID。

    第二个经度是 X,纬度是 Y(不是其他方式)

    SET @pt1 = ST_GeomFromText('POINT (-77.037852 38.898556 )', 4326);
    SET @pt2 = ST_GeomFromText('POINT (-77.043934 38.897147  )',4326);
    

    最后但并非最不重要的一点是,当您计算距离时,您必须将坐标转换为您所在地区可用的本地最精确的 SRID。

    例如,SRID 2877 用于美国(根据您所在的坐标)。

    MYSQL ST_Distance_Sphere 函数不关心输入 SRID 并且总是以米为单位返回结果。

    但这通常是不正确的,所有其他数据库都使用适用于它的指定 SRID 度量单位。

    Bellow 我正在尝试做正确的事情并将 SRID 转换为 2877,如果我们将所有内容都保留为 4326(谷歌墨卡托),即使 MYSQL 也会以相同的方式工作。

    对于 2877,PostGRES 将以英尺为单位返回相同查询的结果,但 MYSQL 仍然返回米。所以输出除以 1609,我们得到了大约 0.34 英里的正确结果。这是一个正确的值,因为使用不同的方法测试过

    SELECT ST_Distance_Sphere(ST_GeomFromText(ST_AsText(@pt1),2877), ST_GeomFromText(ST_AsText(@pt2),2877))/1609.344;
    

    【讨论】:

      【解决方案3】:

      致所有使用 MYSQL 8 的人:

      对于所有 mysql 地理定位功能,必须使用正确的 SRID,否则您将无法获得正确的结果。

      最常用的是 SRID 4326(GPS 坐标、Google 地球)和 SRID 3857(用于 Google 地图、OpenStreetMap 和大多数其他网络地图)。

      两点之间的正确距离计算示例:

      SELECT ST_Distance(ST_GeomFromText('POINT(51.513 -0.08)', 4326), ST_GeomFromText('POINT(37.745 -122.4383)', 4326)) / 1000 AS km;
      

      下面是对这个话题的一个很好的解释: https://medium.com/maatwebsite/the-best-way-to-locate-in-mysql-8-e47a59892443

      mysqlserverteam 有一些很好的解释:
      https://mysqlserverteam.com/spatial-reference-systems-in-mysql-8-0/ https://mysqlserverteam.com/geography-in-mysql-8-0/

      【讨论】:

        【解决方案4】:

        顺便说一句,MySQL 在内部使用一个晦涩且过时的常量来实现这一点。所以这真的取决于你对准确的定义。

        因此,从本质上讲,MySQL 中的半径是从 PostGIS 的一个惰性复制作业中提取的,该作业将半径从英里转换为米,从一个随机的 20 年前的 PostgreSQL 模块中的一个不起眼的常数。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-16
          • 2020-04-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多