mysql中的ST_Distance_Sphere没有给出两个位置之间的准确距离

时间:2016-03-11 12:05:37

标签: mysql sql mysql-workbench

我的requirement是使用map计算给定mysql上两个distance之间的locations。我在名为mysqlST_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_Sphere((38.898556,-77.037852),(38.897147,-77.043934))功能的两个位置lat_lng_distance如下

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 );

获得的结果如下      enter image description here

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

4 个答案:

答案 0 :(得分:5)

ST_DISTANCE_SPHERE要求点数表示为POINT(经度,纬度),在代码中将它们反转

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 |

+ ------------------------------------- + -------- ----------------------------------- +

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

答案 1 :(得分:0)

首先,您无法使用默认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,即使MYSQL将以相同的方式工作,如果我们将所有内容保留为4326(Google mercator)。

对于2877,PostGRES会以相同的查询返回结果,但MYSQL仍会返回米。所以输出分为1609,我们得到了大约0.34英里的正确结果。这是使用不同方法测试的正确值

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

答案 2 :(得分:0)

顺便说一句,MySQL内部使用晦涩且过时的常量来实现此功能。因此,这实际上取决于您对精确的定义。

  

因此,从本质上讲,MySQL的半径是从PostGIS的一个懒惰复制作业中提取的,该工作从一个已有20年历史的旧PostgreSQL模块的晦涩常数将半径(以英里为单位)转换为米。

答案 3 :(得分:0)

对于所有使用MYSQL 8的人:

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

最常用的是SRID 4326(GPS坐标,Google Earth)和SRID 3857(在G​​oogle Maps,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/