我的requirement
是使用map计算给定mysql上两个distance
之间的locations
。我在名为mysql的ST_Distance_Sphere中找到了一个函数,该函数返回两个位置之间的最小球面距离和/或以米为单位的球体上的多个位置。
当我使用ST_Distance_Sphere和lat_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 );
我检查了google maps上两个位置之间的距离,发现lat_lng_distance
接近两个位置之间的实际距离。有人可以告诉我为什么ST_Distance_Sphere没有给出两个位置之间的准确距离吗?
答案 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(在Google 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/