文章目录
前言
最近遇到一个需求,需要查询给定的经纬度坐标点,是否在指定的城市内。 分析需求,需要获取城市区域的边界,再判断目标坐标点是否在边界内。组内的大佬说mysql有这块空间函数的支持,可以了解一下。
所以有了这篇内容。
技术背景
1、MySQL空间数据类型
在MySQL中,空间数据类型是专门用于存储和管理空间数据(如地理位置、几何形状等)的数据类型。这些数据类型使得MySQL能够高效地处理和查询与空间相关的信息。以下是一些MySQL中常见的空间数据类型:
-
GEOMETRY:
- 这是一个
通用的空间数据类型
,可以存储任何类型的空间数据,包括点、线、多边形等。 - 它通常作为其他具体空间数据类型的基类或父类。
- 这是一个
-
POINT:
- 用于存储二维空间中的点,由一对坐标(X, Y)表示。
- 适用于表示具体的地理位置,如城市的位置、用户的坐标等。
-
LINESTRING:
- 用于存储一系列点组成的线段或折线。
- 可以表示道路、河流、路径等线性空间要素。
-
POLYGON:
- 用于存储由
一系列点组成的多边形
,这些点构成了一个闭合的环
。 - 适用于表示区域、地块、湖泊等面状空间要素。
- 用于存储由
此外,MySQL还支持其他更复杂的空间数据类型,如MULTIPOINT(多个点的集合)、MULTILINESTRING(多条线段的集合)、MULTIPOLYGON(多个多边形的集合)以及GEOMETRYCOLLECTION(几何对象的集合)等。
2、MySQL空间函数
-
MySQL空间函数是指用于处理和分析空间数据的函数集合。在MySQL中,空间数据通常指的是具有地理位置信息的数据,如地图数据、几何形状等。这些函数允许用户对空间数据进行各种操作,包括计算距离、判断空间关系、进行几何计算等。它们主要用于支持地理信息系统(GIS)应用、位置服务、物联网(IoT)等领域的数据处理和分析需求。
-
以下是一些常见的MySQL空间函数列表,这些函数主要用于处理和分析空间数据。这些函数通常用于地理信息系统(GIS)、位置服务、物联网(IoT)等领域。
距离计算函数
函数名称 描述 ST_Distance
计算两个几何对象之间的最短距离。 ST_Distance_Sphere
计算球体上两点之间的最短球面距离,考虑了地球的曲率。 空间关系函数
函数名称 描述 ST_Within
判断一个几何对象是否位于另一个几何对象内部。 ST_Contains
判断一个几何对象是否包含另一个几何对象。 ST_Intersects
判断两个几何对象是否相交。 ST_Touches
判断两个几何对象是否相切。 ST_Crosses
判断两个几何对象是否交叉。 ST_Overlaps
判断两个几何对象是否重叠。 几何计算函数
函数名称 描述 ST_Area
计算多边形对象的面积。 ST_Length
计算线对象的长度。 ST_Centroid
计算多边形对象的质心。 ST_Perimeter
计算多边形对象的周长。 ST_ConvexHull
计算一组点的凸包。 缓冲区分析函数
函数名称 描述 ST_Buffer
对几何对象进行缓冲区分析,生成一个以该对象为中心的缓冲区。 空间数据类型转换函数
函数名称 描述 ST_GeomFromText
将WKT(Well-Known Text)格式的几何对象转换为MySQL中的几何对象。 ST_AsText
将MySQL中的几何对象转换为WKT格式的字符串。 ST_GeomFromGeoJSON
将GeoJSON格式的几何对象转换为MySQL中的几何对象。 ST_AsGeoJSON
将MySQL中的几何对象转换为GeoJSON格式的字符串。 其他空间函数
函数名称 描述 ST_StartPoint
获取LineString的起始点。 ST_EndPoint
获取LineString的终点。 ST_NumPoints
获取LineString中的点数。 ST_PointN
获取LineString中的第N个点。 ST_IsClosed
判断LineString是否闭合。 ST_IsValid
判断几何对象是否有效。 请注意,MySQL空间函数的完整列表和功能可能会因MySQL版本的不同而有所差异。为了获取最准确和最新的信息,建议参考MySQL的官方文档或相关权威资源。
目标
学习了解mysql空间函数,了解实现需求需要用到什么空间函数,并创建数据表、造数据实践调用一下对应的空间函数。
实现
建表
-
创建目标坐标点数据表
sqlCREATE TABLE `target_coordinate_table` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `coordinate` geometry NOT NULL COMMENT '坐标点', PRIMARY KEY (`id`), SPATIAL KEY `coordinate` (`coordinate`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='坐标点表';
-
创建城市区域多边形数据表
sqlCREATE TABLE `city_polygon_table` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(100) NOT NULL COMMENT '多边形名称-城市名', `polygon` geometry NOT NULL COMMENT '多边形数据', PRIMARY KEY (`id`), UNIQUE KEY `uk_name` (`name`), SPATIAL KEY `polygon` (`polygon`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='城市区域多边形数据表';
造数
ST_GeomFromText
ST_GeomFromText
是 MySQL 中用于将 Well-Known Text (WKT) 格式的几何数据转换为 MySQL 内部几何数据类型的函数。对于 MULTIPOLYGON
类型的数据,WKT 格式遵循一定的规范来定义多边形集合。
MULTIPOLYGON
的 WKT 格式通常如下所示:
wkt
MULTIPOLYGON(((x1 y1, x2 y2, ..., xn yn, x1 y1)), ((x'1 y'1, x'2 y'2, ..., x'n y'n, x'1 y'1)), ...)
这里是一个具体的例子,包含两个多边形的 MULTIPOLYGON
:
wkt
MULTIPOLYGON(
((10 10, 40 40, 20 20, 10 10)), -- 第一个多边形
((15 15, 35 35, 30 15, 15 15)) -- 第二个多边形
)
要使用 ST_GeomFromText
将这个 MULTIPOLYGON
写入 MySQL 数据库,你可以执行类似以下的 SQL 语句:
sql
INSERT INTO your_table_name (your_geometry_column)
VALUES (ST_GeomFromText('MULTIPOLYGON(((10 10, 40 40, 20 20, 10 10)), ((15 15, 35 35, 30 15, 15 15)))'));
在这个例子中,your_table_name
是包含几何数据列的表的名称,your_geometry_column
是该表中用于存储几何数据的列的名称。这个列应该具有适当的空间数据类型,比如 GEOMETRY
、MULTIPOLYGON
或与之兼容的类型。
目标坐标点数据表insert 数据
sql
INSERT INTO target_coordinate_table (coordinate) VALUES
(ST_GeomFromText('POINT (108.696992 30.933541)')),
(ST_GeomFromText('POINT (108.711323 30.939757)')),
(ST_GeomFromText('POINT (108.769703 31.005251)')),
(ST_GeomFromText('POINT (108.729993 31.007736)')),
(ST_GeomFromText('POINT (106.529617 29.454004)')),
(ST_GeomFromText('POINT (106.53302 29.459989)')),
(ST_GeomFromText('POINT (106.525336 29.453735)')),
(ST_GeomFromText('POINT (106.437501 29.501508)')),
(ST_GeomFromText('POINT (109.102051 30.574327)')),
(ST_GeomFromText('POINT (109.099044 30.573383)'));
城市区域多边形数据表insert数据
sql
INSERT INTO
city_polygon_table (name, polygon)
VALUES ("重庆郊县",
ST_GeomFromText(
'MULTIPOLYGON (((109.098646 30.579115, 109.098655 30.578657, 109.099332 30.577264, 109.100392 30.575931, 109.102051 30.574327, 109.10437 30.572002, 109.10536 30.571059, 109.106124 30.570777,
109.103692 30.56583, 109.098819 30.57029, 109.09683 30.57217, 109.095353 30.574395, 109.093476 30.577624, 109.092868 30.578731,
109.098646 30.579115)))'
));
测试
查询目标点是否在指定的城市区域内
执行SQL:
sql
select coordinate
from target_coordinate_table tct
where st_within(tct.coordinate, (select polygon from city_polygon_table cpt where id = 1)) = 1;
查询结果:
查询两个目标点的距离
执行SQL
sql
select coordinate, st_distance_sphere(corrdinate, point(106.529617,29.454004)) as distance
from target_coordinate_table;
查询结果:
查询目标点半径范围内的其他点
sql
SELECT *
FROM (
SELECT
coordinate,
st_distance_sphere(coordinate, point(106.529617,29.454004)) as distance
FROM
target_coordinate_table
) AS subquery
WHERE subquery.distance < 20000;
小结
本文记录了学习和实践MySQL中的空间数据类型和空间函数的过程,并成功实现了查询目标坐标点是否在指定城市区域内的需求。总结如下:
-
MySQL空间数据类型 :常见的类型包括
GEOMETRY
、POINT
、LINESTRING
、POLYGON
等,以及它们各自的应用场景。这些数据类型为存储和管理空间数据提供了高效的方式,使得MySQL能够处理和查询与空间相关的信息。 -
MySQL空间函数 :包括距离计算函数(如
ST_Distance
、ST_Distance_Sphere
)、空间关系函数(如ST_Within
、ST_Contains
、ST_Intersects
等)、几何计算函数(如ST_Area
、ST_Length
等)以及其他相关函数,后续可按需使用。 -
实践应用:
- 我们创建了目标坐标点数据表和城市区域多边形数据表,并插入了相应的数据。
- 通过使用
ST_Within
函数,我们成功查询了目标坐标点是否在指定的城市区域内。 - 我们还实践了查询两个目标点的距离以及查询目标点半径范围内的其他点,验证了MySQL空间函数的有效性和实用性。
-
注意事项:
-
在使用MySQL空间函数时,需要注意函数的参数和返回值类型,确保它们与数据表中的空间数据类型相匹配。
-
对于复杂的空间查询,可能需要考虑查询的性能和优化策略,如使用空间索引、合理的数据结构等。
-
问题记录:
1、写入多边形区域数据报格式错误
报错信息 "Data truncation: Invalid GIS data provided to function st_geometryfromtext." 指出你提供的 GIS 数据在解析时遇到了问题。这通常是因为数据格式错误、数据点不符合规范、或者多边形没有正确闭合等原因造成的。
需要留意提供的 MULTIPOLYGON
数据中,是否有以下问题:
- 多边形未闭合:每个多边形都应该是一个闭合的环,即第一个点和最后一个点应该是相同的。每个多边形都要达到这个要求。
- 数据点顺序问题:多边形的点应该按照顺时针或逆时针的顺序排列,这通常是为了定义多边形的"内部"和"外部"。如果点的顺序混乱,可能会导致解析错误。
- 坐标值超出范围或格式错误:确保所有的坐标值都在合理的范围内,并且格式正确(例如,经度应在 -180 到 180 之间,纬度应在 -90 到 90 之间)。
- 多余或缺失的括号 :
MULTIPOLYGON
的定义中括号的使用非常重要,确保每个多边形和整个多边形集合的括号都正确匹配。
2、ST_Within
查询点是否在多边形内,不包含边界点
在地理空间数据查询中,ST_Within
函数用于判断一个几何对象是否完全位于另一个几何对象内部。
ST_Within
函数的一个核心定义特性:几何体的边界不被视为几何体内部的一部分。
为了处理边界点的情况,可以考虑使用其他空间查询函数或方法,例如:
- ST_Touches:用于判断两个几何对象是否相接触,但不重叠。这可以捕捉到边界点接触的情况。
- ST_Intersects:用于判断两个几何对象是否相交。这个函数会考虑几何对象的内部和边界,因此如果边界点相交,它也会返回真(TRUE)。