当前位置: 首页 > news >正文

mysql存储地理信息的方法

MySQL 存储地理信息通常使用 GEOMETRY 数据类型或其子类型(如 POINT, LINESTRING, POLYGON 等)。为了支持这些数据类型,MySQL 提供了 SPATIAL 索引,这允许我们执行高效的地理空间查询。

1. 创建支持地理信息的表

首先,我们需要一个包含 GEOMETRY 或其子类型列的表。以下是一个示例,展示如何创建一个包含 POINT 类型的表:

CREATE TABLE locations (  id INT AUTO_INCREMENT PRIMARY KEY,  name VARCHAR(255) NOT NULL,  position POINT NOT NULL,  SPATIAL INDEX(position)  -- 为位置列创建空间索引  
) ENGINE=InnoDB;

2. 插入地理信息数据

我们可以使用 GeomFromText()PointFromText() 函数插入地理数据。以下是如何插入一个点的示例:

INSERT INTO locations (name, position)  
VALUES ('Location A', GeomFromText('POINT(10 20)'));  
-- 或者使用 PointFromText  
INSERT INTO locations (name, position)  
VALUES ('Location B', PointFromText('POINT(30 40)'));

3. 查询地理信息数据

我们可以使用 MBRContains(), Distance_Sphere(), ST_Distance_Sphere() 等函数来查询地理数据。以下是一些示例:

3.1查找指定矩形区域内的位置

-- 查找位置在 (0, 0) 到 (20, 20) 矩形区域内的所有位置  
SELECT * FROM locations  
WHERE MBRContains(  GeomFromText('POLYGON((0 0, 20 0, 20 20, 0 20, 0 0))'),  position  
);

3.2查找距离特定点一定距离内的位置

注意:这里使用了 Distance_Sphere() 函数,它基于地球是完美球体的假设。对于更精确的计算,我们可以使用 ST_Distance_Sphere() 并指定地球半径。

-- 查找距离 (15, 15) 点 10 公里内的所有位置  
-- 假设地球半径为 6371 公里(平均半径)  
SELECT *, (6371 * acos(cos(radians(15))   * cos(radians(X(position)))   * cos(radians(Y(position)) - radians(15))   + sin(radians(15))   * sin(radians(X(position))))) AS distance_km   
FROM locations   
HAVING distance_km < 10;

3.3使用 ST_Distance_Sphere() 查找距离

这是一个更精确的距离计算示例,它使用 ST_Distance_Sphere() 函数并指定地球的平均半径。

-- 查找距离 (15, 15) 点 10 公里内的所有位置  
SELECT *, ST_Distance_Sphere(point(15, 15), position, 6371) AS distance_km   
FROM locations   
HAVING distance_km < 10;

注意:上述查询中的距离计算是基于 Haversine 公式的简化版本,它假设地球是一个完美的球体。在实际应用中,我们可能需要使用更复杂的算法来考虑地球的不规则形状。

此外,我们还可以使用 MySQL 的其他地理空间函数和操作符来执行更复杂的地理空间查询和操作。

4.查询地理信息进阶示例

我们可以探讨一个更复杂的示例,该示例涉及POLYGON地理数据类型,并使用ST_Contains函数来检查一个点是否位于多边形内部。同时,我们也会使用ST_Distance_Sphere函数来计算点与多边形中心点的距离。

4.1创建表并插入数据

首先,我们创建一个包含POLYGON列的表,并插入一些多边形数据。

CREATE TABLE polygons (  id INT AUTO_INCREMENT PRIMARY KEY,  name VARCHAR(255) NOT NULL,  shape POLYGON NOT NULL,  SPATIAL INDEX(shape)  
) ENGINE=InnoDB;  INSERT INTO polygons (name, shape)  
VALUES ('Polygon A', GeomFromText('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))'));  
INSERT INTO polygons (name, shape)  
VALUES ('Polygon B', GeomFromText('POLYGON((20 20, 30 20, 30 30, 20 30, 20 20))'));  -- 创建一个包含点的表  
CREATE TABLE points (  id INT AUTO_INCREMENT PRIMARY KEY,  name VARCHAR(255) NOT NULL,  position POINT NOT NULL,  SPATIAL INDEX(position)  
) ENGINE=InnoDB;  INSERT INTO points (name, position)  
VALUES ('Point 1', GeomFromText('POINT(5 5)'));  
INSERT INTO points (name, position)  
VALUES ('Point 2', GeomFromText('POINT(25 25)'));

4.2查询点是否在多边形内部,并计算距离

现在,我们可以编写一个查询来检查点是否位于多边形内部,并计算这些点与多边形中心点的距离。

-- 假设我们想要检查'Point 1'和'Point 2'是否分别位于'Polygon A'和'Polygon B'内部  
-- 并计算它们与各自多边形中心点的距离  -- 首先,我们需要计算每个多边形的中心点  
SET @polygonA_center = ST_Centroid(GeomFromText('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))'));  
SET @polygonB_center = ST_Centroid(GeomFromText('POLYGON((20 20, 30 20, 30 30, 20 30, 20 20))'));  -- 然后,我们可以使用这些中心点与点表中的点进行比较和距离计算  
SELECT   p.name AS point_name,  p.position,  CASE   WHEN ST_Contains(pg.shape, p.position) THEN 'Inside'  ELSE 'Outside'  END AS location_status,  ST_Distance_Sphere(p.position, CASE pg.name WHEN 'Polygon A' THEN @polygonA_center ELSE @polygonB_center END, 6371) AS distance_km  
FROM   points p  
JOIN   polygons pg ON (  (p.name = 'Point 1' AND pg.name = 'Polygon A') OR  (p.name = 'Point 2' AND pg.name = 'Polygon B')  );

这个查询首先计算了两个多边形的中心点,并使用JOIN语句将点表与多边形表连接起来。它使用ST_Contains函数来检查点是否位于多边形内部,并使用ST_Distance_Sphere函数来计算点与对应多边形中心点的距离(以公里为单位)。注意,我们使用了CASE语句来根据点的名称选择正确的多边形中心点进行计算。

这个查询将返回每个点的名称、位置、是否在多边形内部的状态以及与对应多边形中心点的距离。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • jmeter之MD5加密接口请求教程
  • C语言-atoi()库函数的模拟实现
  • 摩尔投票法——代码实现及注释(力扣169题:找出列表中多数元素)
  • 源码编译安装LAMP
  • R可视化:另类的箱线图
  • Vue3实战笔记(47)— 一探emit奥秘——组件间通信的艺术与实践
  • React 微信扫码登陆网页
  • iOS推送证书过期处理
  • Java:String、StringBuffer和StringBuilder的区别
  • linux安装python第三方库情况
  • 防火墙基础基础篇:NAT转发功能之——Easy IP方式详解
  • dcache-android框架中的设计模式详解
  • 深圳比创达EMC|EMI电磁干扰行业:行业发展的关键与挑战
  • 汇编原理(二)寄存器——内存访问
  • 掌握SQL注入检测:深入理解SQLMAP工具
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • create-react-app做的留言板
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • Git同步原始仓库到Fork仓库中
  • Hibernate最全面试题
  • Koa2 之文件上传下载
  • Mysql数据库的条件查询语句
  • Object.assign方法不能实现深复制
  • React的组件模式
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • Unix命令
  • 飞驰在Mesos的涡轮引擎上
  • 简析gRPC client 连接管理
  • 力扣(LeetCode)21
  • 区块链共识机制优缺点对比都是什么
  • 使用common-codec进行md5加密
  • 听说你叫Java(二)–Servlet请求
  • 微信公众号开发小记——5.python微信红包
  • 微信小程序--------语音识别(前端自己也能玩)
  • 扩展资源服务器解决oauth2 性能瓶颈
  • ​必胜客礼品卡回收多少钱,回收平台哪家好
  • # Maven错误Error executing Maven
  • # Redis 入门到精通(八)-- 服务器配置-redis.conf配置与高级数据类型
  • # Redis 入门到精通(九)-- 主从复制(1)
  • # 数仓建模:如何构建主题宽表模型?
  • #{}和${}的区别?
  • (10)ATF MMU转换表
  • (20050108)又读《平凡的世界》
  • (C语言)球球大作战
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (读书笔记)Javascript高级程序设计---ECMAScript基础
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (转)fock函数详解
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • **python多态
  • .apk 成为历史!