mysql使用Haversine 公式和ST_Distance_Sphere 函数实现附近的人功能

 更新时间:2023年08月25日 10:00:47   作者:水滴技术  
使用 MySQL 来实现“附近的人”功能,可以通过Haversine 公式和ST_Distance_Sphere 函数两种方式来实现,这篇文章主要介绍了mysql实现附近的人功能,需要的朋友可以参考下

对于“附近的人”功能,在生活中是比较常用的,像外卖app附近的美食,共享单车app里附近的车辆等等。我们之前使用 ElasticSearch 实现过该功能,本篇文章我们介绍如何通过 MySQL 来实现“附近的人”功能。

在这里插入图片描述

ST_Distance_Sphere 函数

在 MySQL 中,ST_Distance_Sphere 函数是一个地理空间函数,用于计算两个地理位置之间的球面距离。它基于球体模型进行计算,并返回两个点之间的距离结果。

ST_Distance_Sphere 函数的语法如下:

ST_Distance_Sphere(point1, point2)

其中,point1point2 是表示地理位置的 POINT 类型的参数。

示例一:计算北京站到北京西站的距离

以下是一个使用 ST_Distance_Sphere 函数计算球面距离的示例:

-- 北京站 116.427322,39.902822    北京西站  116.322083,39.8949
SELECT ST_Distance_Sphere(
          POINT(116.427322,39.902822), 
          POINT(116.322083,39.8949)
       ) AS distance;

在上述示例中,我们使用 POINT 类型的参数表示两个地理位置点,分别是北京站(经度 116.427322,纬度 39.902822)和北京西站(经度 116.322083,纬度 39.8949)。然后,我们调用 ST_Distance_Sphere 函数来计算这两个点之间的球面距离,并将结果命名为 distance

返回结果:

distance
-----------------------
9020.641566063772

ST_Distance_Sphere 函数的返回值是以米为单位的球面距离,可以根据需要将结果转换为千米。上面示例中可以看出,北京站到北京西站的距离约为9公里。

需要注意的是,使用 ST_Distance_Sphere 函数进行球面距离计算需要 MySQL 版本 8.0.17 或更高版本,并且需要在数据库中启用地理空间功能。

示例二:查询“附近的人”

要实现"附近的人"功能,可以使用MySQL的ST_Distance_Sphere 函数和索引来处理地理位置数据。下面是一个基本的实现步骤:

(1)创建GEO测试表:其中包括id 主键、location地理位置信息。地理位置信息可以使用POINT类型来表示。

CREATE TABLE `test_geo` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `location` point DEFAULT NULL,
  PRIMARY KEY (`id`)
);

(2)添加地理位置数据:向表中插入地理位置数据。

INSERT INTO `test_geo`(`id`, `location`) 
VALUES 
  (1, POINT(116.39775,39.92029)),
  (2, POINT(116.395947,39.916208),
  (3, POINT(116.410624,39.91871)),
  (4, POINT(116.397235,39.909823)),
  (5, POINT(116.385304,39.917591)),
  (6, POINT(116.396548,39.92832))
;

(3)创建地理索引:为该表的地理位置字段创建索引,以便进行空间查询。

CREATE SPATIAL INDEX idx_location ON test_geo (location);

(4)查询附近的人:使用地理空间函数进行附近的人查询。

  SELECT
    *,
    ST_Distance_Sphere ( POINT ( 116.410539, 39.912983 ), location ) AS distance -- 返回距离,单位M
  FROM
    test_geo 
  WHERE
    ST_Distance_Sphere ( POINT ( 116.410539, 39.912983 ), location ) <= 2000 -- 两公里内
  ORDER BY
    distance -- 由近及远排序
  ; 

上述查询使用了ST_Distance_Sphere函数来计算两个地理位置之间的球面距离,POINT ( 116.410539, 39.912983 ) 是你的坐标,2000是查询半径。这个查询将返回在给定半径范围内的数据。

查询结果:

在这里插入图片描述

Haversine 公式

ST_Distance_Sphere 函数要求MySQL 的版本为 8.0.17 或更高,对于低版本的 MySQL 该怎么办呢?我们可以使用 Haversine 公式来实现。

Haversine 是一种常用的球面三角函数,用于计算两个球面位置之间的球面距离。它是根据地球的球体模型进行计算的,可以用于近似计算两个经纬度坐标之间的球面距离。

Haversine 公式基于球面三角学和经纬度之间的关系。它的公式如下:

a = sin²(Δlat/2) + cos(lat1) * cos(lat2) * sin²(Δlon/2)
c = 2 * atan2(√a, √(1-a))
d = R * c

其中:

  • lat1lat2 是两个点的纬度(以弧度表示)。
  • lon1lon2 是两个点的经度(以弧度表示)。
  • Δlat 是纬度之差,即 lat2 - lat1
  • Δlon 是经度之差,即 lon2 - lon1
  • R 是地球的半径,常用的单位是千米或英里。

通过应用 Haversine 公式,可以近似计算出两个经纬度坐标之间的球面距离。这个公式考虑了球体的曲率,因此对于较短距离的计算具有较高的精度。然而,对于较长距离,特别是跨越大片陆地或海洋的距离,Haversine 公式可能会引入一定的误差。

在使用 Haversine 公式进行计算时,需要注意输入的经纬度必须使用弧度表示。如果经纬度是以度数表示,需要将其转换为弧度形式进行计算。

示例一:计算北京站到北京西站的距离

以下是一个使用Haversine公式计算球面距离的示例:

-- 北京站 116.427322,39.902822    北京西站  116.322083,39.8949
select (2 * 6371 * ASIN(SQRT(
        POWER(SIN((RADIANS(39.902822) - RADIANS(39.8949)) / 2), 2) +
        COS(RADIANS(39.902822)) * COS(RADIANS(39.8949)) * POWER(SIN((RADIANS(116.427322) - RADIANS(116.322083)) / 2), 2)
    ))) AS distance

在上述示例中,我们分别将北京站(经度 116.427322,纬度 39.902822)和北京西站(经度 116.322083,纬度 39.8949)的经纬度数据带入Haversine公式中,然后就可以计算出这两个点之间的球面距离,并将结果命名为 distance

返回结果:

distance
-----------------------
9.020661388581411

Haversine公式的返回值是以千米为单位的球面距离。

示例二:查询“附近的人”

我们可以使用Haversine公式来实现"附近的人"功能,下面是一个基本的实现步骤:

(1)创建GEO测试表:其中包括id 主键、地理位置信息。地理位置信息可以使用lng表示经度,lat表示纬度。

CREATE TABLE `test_geo` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `lng` double DEFAULT NULL,
  `lat` double DEFAULT NULL,
  PRIMARY KEY (`id`)
);

(2)添加地理位置数据:向表中插入地理位置数据。

INSERT INTO `test_geo`(`id`, `lng`, `lat`) 
VALUES 
  (1, 116.39775, 39.92029),
  (2, 116.395947, 39.916208),
  (3, 116.410624, 39.91871),
  (4, 116.397235, 39.909823),
  (5, 116.385304, 39.917591),
  (6, 116.396548, 39.92832)
;

(3)查询附近的人:使用Haversine公式进行附近的人查询。

 SELECT
  *,
  (2 * 6371 * ASIN(
      SQRT(
        POWER( SIN(( RADIANS( 39.912983 ) - RADIANS( lat )) / 2 ), 2 ) + COS(
          RADIANS( 39.912983 )) * COS(
        RADIANS( lat )) * POWER( SIN(( RADIANS( 116.410539 ) - RADIANS( lng )) / 2 ), 2 ) 
      ))) AS distance  -- 返回距离,单位KM
FROM
  test_geo 
WHERE
  (2 * 6371 * ASIN(
      SQRT(
        POWER( SIN(( RADIANS( 39.912983 ) - RADIANS( lat )) / 2 ), 2 ) + COS(
          RADIANS( 39.912983 )) * COS(
        RADIANS( lat )) * POWER( SIN(( RADIANS( 116.410539 ) - RADIANS( lng )) / 2 ), 2 ) 
      ))) <= 2  -- 两公里内
ORDER BY
  distance -- 由近及远排序
;

上述查询使用了Haversine公式来计算两个地理位置之间的球面距离,116.410539, 39.912983 是你的坐标,2是查询半径。这个查询将返回在给定半径范围内的数据。

查询结果:

在这里插入图片描述

总结

使用 MySQL 来实现“附近的人”功能,可以通过Haversine 公式和ST_Distance_Sphere 函数两种方式来实现。对于低版本的 MySQL 只能使用Haversine 公式,但我们还是推荐升级你的 MySQL(8.0.17版本或更新),因为使用ST_Distance_Sphere 函数不仅使用简单,而且它还支持空间索引,使得查询速度更快。

到此这篇关于mysql实现附近的人功能的文章就介绍到这了,更多相关mysql附近的人内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL中Case When用法及说明

    MySQL中Case When用法及说明

    这篇文章主要介绍了MySQL中Case When用法及说明,具有很好的参考价值,希望对大家有所帮助。
    2022-12-12
  • MySQL常见的脚本语句格式参考指南

    MySQL常见的脚本语句格式参考指南

    无论是运维、开发、测试,还是架构师,数据库技术是一个必备加薪神器,下面这篇文章主要给大家介绍了关于MySQL常见的脚本语句格式参考指南的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • windows下安装、卸载mysql服务的方法(mysql 5.6 zip解压版安装教程)

    windows下安装、卸载mysql服务的方法(mysql 5.6 zip解压版安装教程)

    这篇文章主要介绍了windows下安装、卸载mysql服务的方法(zip解压版安装),需要的朋友可以参考下
    2016-06-06
  • MySql事务无法回滚的原因有哪些

    MySql事务无法回滚的原因有哪些

    使用MySQL时,如果发现事务无法回滚,但Hibernate、Spring、JDBC等配置又没有明显问题,到底是什么原因,下面与大家分享下
    2014-07-07
  • Mysql分组查询每组最新的一条数据的五种实现方法

    Mysql分组查询每组最新的一条数据的五种实现方法

    在写报表功能时遇到一个需要根据用户id分组查询最新一条钱包明细数据的需求,本文主要介绍了Mysql分组查询每组最新的一条数据的五种实现方法,感兴趣的可以了解一下
    2024-08-08
  • 删除MySQL中所有表的外键的两种方法

    删除MySQL中所有表的外键的两种方法

    这篇文章主要介绍了删除MySQL中所有表的外键的两种方法,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-05-05
  • MySQL存储过程图文实例讲解

    MySQL存储过程图文实例讲解

    虽然MySQL的存储过程一般情况下是不会使用到的,但是在一些特殊场景中,还是有需求的,下面这篇文章主要给大家介绍了关于MySQL存储过程的相关资料,需要的朋友可以参考下
    2022-03-03
  • MYSQL SERVER收缩日志文件实现方法

    MYSQL SERVER收缩日志文件实现方法

    这篇文章主要介绍了MYSQL SERVER收缩日志文件实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • mysql事务处理用法与实例代码详解

    mysql事务处理用法与实例代码详解

    这篇文章主要介绍了mysql事务处理用法与实例代码详解,详细的介绍了事物的特性和用法并实现php和mysql事务处理例子,非常具有实用价值,需要的朋友可以参考下
    2018-12-12
  • MySQL5.7 如何通过逻辑备份迁移到GreatSQL及注意事项

    MySQL5.7 如何通过逻辑备份迁移到GreatSQL及注意事项

    在将数据库从MySQL 5.7迁移到GreatSQL8.0.32时,由于数据量较小且关注安全性,决定使用mysqldump执行逻辑备份,并将数据导入GreatSQL,这篇文章主要介绍了MySQL5.7 通过逻辑备份迁移到GreatSQL注意事项,需要的朋友可以参考下
    2024-06-06

最新评论