MySQL 实战(一):实现“附近的人”功能

❤️ 个人主页:水滴技术
🚀 支持水滴:点赞👍 + 收藏⭐ + 留言💬
🌸 订阅专栏:MySQL 教程:从入门到精通

文章目录

  • ST_Distance_Sphere 函数
    • 示例一:计算北京站到北京西站的距离
    • 示例二:查询“附近的人”
  • Haversine 公式
    • 示例一:计算北京站到北京西站的距离
    • 示例二:查询“附近的人”
  • 总结
  • 热门专栏


大家好,我是水滴~~

对于“附近的人”功能,在生活中是比较常用的,像外卖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 -- 返回距离,单位MFROMtest_geo WHEREST_Distance_Sphere ( POINT ( 116.410539, 39.912983 ), location ) <= 2000 -- 两公里内ORDER BYdistance -- 由近及远排序; 

上述查询使用了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
FROMtest_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 BYdistance -- 由近及远排序
;

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

查询结果:

在这里插入图片描述

总结

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

热门专栏

👍 《Python入门核心技术》
👍 《IDEA 教程:从入门到精通》
👍 《Java 教程:从入门到精通》
👍 《MySQL 教程:从入门到精通》
👍 《大数据核心技术从入门到精通》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/102037.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

两阶段提交:详解数据库宕机引起的主从不一致问题、redolog与binlog的两阶段提交

0、基础知识and问题 从基础上我们了解&#xff1a; &#xff08;1&#xff09;redolog作为数据库保证持久化的日志&#xff0c;在update事务提交后就会按一定的策略刷入磁盘中&#xff0c;在刷入后&#xff0c;即使数据库断电宕机&#xff0c;mysql也能从redolog中恢复数据到磁…

NineData中标移动云数据库传输项目(2023)

近日&#xff0c;玖章算术NineData智能数据管理平台成功中标《2023年移动云数据库传输服务软件项目》&#xff0c;中标金额为406万。这标志着玖章算术NineData平台已成功落地顶级运营商行业&#xff0c;并在数据管理方面实现了大规模应用实践。 NineData中标2023移动云数据库传…

OpenCV使用CMake和MinGW-w64的编译安装

OpenCV使用CMake和MinGW-w64的编译安装中的问题 问题&#xff1a;gcc: error: long: No such file or directory** C:\PROGRA~2\Dev-Cpp\MinGW64\bin\windres.exe: preprocessing failed. modules\core\CMakeFiles\opencv_core.dir\build.make:1420: recipe for target ‘modul…

基于nginx禁用访问ip

一、背景 网络安全防护时&#xff0c;禁用部分访问ip,基于nginx可快速简单实现禁用。 二、操作 1、创建 conf.d文件夹 在nginx conf 目录下创建conf.d文件夹 Nginx 扩展配置文件一般在conf.d mkdir conf.d 2、新建blocksip.conf文件 在conf.d目录新建禁用ip的扩展配置文…

Bandicam 班迪录屏 安装使用教程

Bandicam是一款非常流行的录屏软件&#xff0c;可以在Windows系统上轻松录制游戏或其他应用程序的视频&#xff0c;支持高清、压缩方式选择、多媒体编码、按键记录、水印等。下面是Bandicam安装使用教程。 1、下载Bandicam安装程序 在官方网站或其他可靠的下载站点上下载Band…

如何保障Facebook账号登录稳定

当谈到保障Facebook账号的稳定性时&#xff0c;我们不得不提到那些令人头疼的情况——Facebook账号被封。尽管我们已经踏入数字化的未来&#xff0c;但是被封号似乎是一个时常困扰着社交媒体用户的问题。那么&#xff0c;让我们来看看一些常见的Facebook账号被封的原因&#xf…

python爬虫实战(3)--爬取某乎热搜

1. 分析爬取地址 打开某乎首页&#xff0c;点击热榜 这个就是我们需要爬取的地址&#xff0c;取到地址某乎/api/v3/feed/topstory/hot-lists/total?limit50&desktoptrue 定义好请求头&#xff0c;从Accept往下的请求头全部复制&#xff0c;转换成json headers {Accep…

基于Python科研论文绘制学习 - task2

Matplotlib 1、subplot&#xff08;&#xff09; matplotlib.pyplot模块提供了一个 subplot() 函数&#xff0c;它可以均等地划分画布&#xff0c;该函数的参数格式如下&#xff1a; plt.subplot(nrows, ncols, index) nrows 与 ncols 表示要划分几行几列的子区域&#xff0…

【工程优化问题】基于鲸鱼、萤火虫、灰狼优化算法的张力、压缩弹簧设计问题研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

问道管理:数字经济概念走势强劲,竞业达、久其软件等涨停,观想科技等大涨

信创、智慧政务等数字经济概念22日盘中走势微弱&#xff0c;截至发稿&#xff0c;观想科技、慧博云通涨超15%&#xff0c;竞业达、中远海科、久其软件等涨停&#xff0c;云赛智联、延华智能、汇纳科技涨约9%&#xff0c;天玑科技、安硕信息、思特奇、零点稀有涨逾7%。 音讯面上…

MyBatis的核心技术掌握,简单易懂

目录 一.MyBatis中的动态SQL 二.MyBatis中的模糊查询 1. # 符号 2. $ 符号 ---问题 ---所以大家知道 # 和 $ 在MyBatis中的模糊查询中的区别了嘛&#xff1f;&#xff1f; 三.MyBatis 中的结果映射 1. resultType&#xff1a; 2. resultMap&#xff1a; ---问题 ---…

PHP求职招聘系统Dreamweaver开发mysql数据库web结构php编程计算机网页

一、源码特点 PHP 求职招聘系统是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 源码 https://download.csdn.net/download/qq_41221322/88240283 论文 https://down…

ORB-SLAM系列算法演进

ORB-SLAM算法是特征点法的代表&#xff0c;当前最新发展的ORB-SLAM3已经将相机模型抽象化&#xff0c;适用范围非常广&#xff0c;虽然ORB-SLAM在算法上的创新并不是很丰富&#xff0c;但是它在工程上的创新确实让人耳目一新&#xff0c;也能更好的为AR、机器人的算法实现落地。…

裂缝检测,只依赖OPENCV,基于YOLO8S

裂缝检测&#xff0c;只依赖OPENCV&#xff0c;YOLOV8S 现在YOLOV8S训练目标非常方便&#xff0c;可以直接转换成ONNX让OPENCV调用&#xff0c;支持C/PYTHON&#xff0c;原理很简单&#xff0c;自己找博客&#xff0c;有兴趣相互交流

Java学习笔记37

Java笔记37 TCP案例 TCP实现发送消息 下面我们来分别编写一个客户端程序和一个服务端程序&#xff0c;使用用户端给服务端发送一句消息&#xff0c;然后使用服务端接收用户端发送过来的这句消息并打印输出。 客户端&#xff1a; 创建一个与服务端Socket类的实例对象&#xf…

基于swing的教务管理系统java jsp学生教师信息mysql源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 基于swing的教务管理系统 系统有3权限&#xff1a;管…

伦敦金短线好还是长线好

在伦敦金投之中&#xff0c;长期有一个争论很久的问题&#xff0c;那就是伦敦金投资究竟是长线好还是短线好&#xff1f;不同的投资者对这个问题有不同的看法&#xff0c;一般认为&#xff0c;伦敦金投资比较适合短线交易。笔者也将讨论这个问题&#xff0c;看看伦敦金投资是不…

谁偷走了我的存储容量?预留空间OP参上!

大家好&#xff0c;我是五月。 前言 不知道你有没有发现&#xff0c;每当买回来一块U盘&#xff0c;插入电脑发现永远比所标的容量小。 到底是谁偷走了我的容量&#xff1f; 真凶就是预留空间&#xff08;Over Provisioning&#xff09;&#xff0c;简称OP。 预留空间OP是…

【Go语言】基于Socket编程的P2P通信程序示例

Go语言的Socket编程实现为开发者提供了一种高效且强大的方式来实现网络通信。通过Go语言的并发模型和内置的网络库&#xff0c;如net包&#xff0c;开发者可以轻松地创建基于套接字的通信应用。Go语言的goroutine和channel机制使并发处理变得简单&#xff0c;能够轻松处理多个连…

【硕士论文完美复现】【价格型需求响应】基于需求侧响应的配电网供电能力综合评估(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…