mysql 距离计算排序

应用场景为已知某用户的地理位置,即经纬度,获取他附近的商家信息按距离远近排序

从mysql5.6.1以后开始支持 ST_Distance 函数用来计算对象的空间关系,并且支持地理参数类型为 Point和Point,或point和MultiPoint(不限制顺序)

从mysql8.0.18开始支持所有几何类型的地理SRS自变量的距离计算

而从mysql5.7.6以后新增加一个方法用来测球面上两点距离

ST_Distance_Sphere(g1, g2 [, radius]) radius指球体半径,缺省值为地球半径

SRS: 用来描述几何的定义空间被称为空间参照系

废话说了这么多直接上干货

例如:

 沈丘县周口市中国466300
         "geometry" : {
            "location" : {
               "lat" : 33.4096812,
               "lng" : 115.0984158
            }

拱墅区杭州市中国310000
         "geometry" : {
            "location" : {
               "lat" : 30.2734437,
               "lng" : 120.155262
            }

计算两地之间的距离单位米

select ST_Distance_sphere(point(120.155262, 30.2734437), point(115.0984158, 33.4096812));

mysql 距离计算排序

mysql 距离计算排序

与工具测算的相差27米,误差也算可以接收,误差的原因猜测是半径取值问题,根据公式计算

select ST_Distance_sphere(point(0, 0), point(180, 0)) /pi(); 得出ST_Distance_sphere 函数的地球半径取值为 6370986 米

如果是从程序中处理也可以使用字符串的形式

select ST_Distance_sphere(PointFromText('point(120.155262 30.2734437)'),PointFromText('point(115.0984158 33.4096812)'));

注意:point坐标的第一个参数是经度(-180,180),第二个参数是维度(-90,90),mysql中命令中point坐标用 逗号 分隔,字符串的point 用 空格 分隔


另外一点是关于经纬的存储精度问题

维基百科中精确到固定位数可辨识的程度表

mysql 距离计算排序

经度取值范围为[0,180],纬度的取值范围为[0,90],一般情况下辨识度达到人 这一级别就可以,即6位小数,因此选择为

longitudes(经度): decimal(9,6)
latitudes (纬度): decimal(8,6)

经度应该比纬度是要多存一位。

另外如果需要达到专业的测量结果,可以选用最高精度:

longitudes(经度): decimal(11,8)
latitudes (纬度): decimal(10,8)

维基百科说明decimal就是用于存储地理位置信息的,所以选择 decimal 作为存储类型也是可以经得住推敲的