登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  MySQL

MySQL ST_NumInteriorRing 怎样统计多边形内部孔洞

来源:17golang原创

时间:2026-10-27 08:32:59 279浏览 收藏

要统计 MySQL 中一个 Polygon 有几个内部孔洞,直接调用 ST_NumInteriorRing(poly) 即可。它返回内部环的数量,外部边界不计入这个数字;例如一个外环加两个内部环,结果就是 2。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/gis-polygon-property-functions.html

最小写法是 ST_NumInteriorRing(ST_GeomFromText(wkt))。若只是想知道孔洞数,用它;若还要查看某个孔洞的边界,再配合 ST_InteriorRingN(),其中 N 从 1 开始。

问题:外环和孔洞为什么不能一起数

WKT 中的 Polygon 由一个外环和零个或多个内部环组成。外环描述多边形的外部边界,内部环描述被挖空的区域。ST_NumInteriorRing() 只返回后者的数量,因此不要把 WKT 中的环总数直接当成孔洞数:环总数减去外环才是内部环数量。

MySQL 8.4 手册同时列出单数形式 ST_NumInteriorRing() 和复数形式 ST_NumInteriorRings()。两者都用于返回 Polygon 的内部环数量,团队可以按现有 SQL 的命名习惯选择。

最小配方:用 ST_NumInteriorRing 统计一个孔洞

下面的 WKT 有一个外环和一个内部环。SQL 注释只解释示例的几何结构,不代表在本文环境中实际执行。

-- 外环是 0,0 到 10,10;内环是 2,2 到 4,4,表示一个孔洞
SET @poly = 'POLYGON((0 0,10 0,10 10,0 10,0 0),(2 2,2 4,4 4,4 2,2 2))';

-- 统计 Polygon 的内部环数量,外环不会计入结果
SELECT ST_NumInteriorRing(ST_GeomFromText(@poly)) AS hole_count;

这个结构对应的结果应理解为 hole_count = 1。如果使用手册示例中的复数别名,写法如下:

-- 复数别名表达同一个统计意图,便于按团队命名习惯阅读
SELECT ST_NumInteriorRings(ST_GeomFromText(@poly)) AS hole_count;
Polygon 外环和两个内部环连接到 ST_NumInteriorRing 孔洞数量结果的说明图
图1:Polygon 外环、内部环与孔洞数量统计的静态结构图,不是运行截图或执行结果。

变体:两个内部环时结果如何理解

一个 Polygon 可以包含多个内部环。下面把第二个孔洞加入同一个 WKT,函数返回的数量随内部环数量变化,外环仍然只算边界、不算孔洞。

-- 一个外环加两个内部环,两个内环分别代表两个独立孔洞
SET @poly_two_holes = 'POLYGON((0 0,12 0,12 12,0 12,0 0),
  (2 2,2 4,4 4,4 2,2 2),
  (7 7,7 10,10 10,10 7,7 7))';

-- 返回内部环数量,不把外环加到统计结果中
SELECT ST_NumInteriorRing(ST_GeomFromText(@poly_two_holes)) AS hole_count;

这类查询适合先做数据概览,例如把结果作为“地块孔洞数”展示。它回答的是“有几个内部环”,不是孔洞面积、孔洞周长,也不是多边形是否几何有效;这些是不同的问题,不能从数量列推导。

关键边界:N 从 1 开始,外环没有这个编号

统计数量后,如果还要检查某个孔洞的边界,可以使用 ST_InteriorRingN(poly, N)。官方手册说明内部环编号从 1 开始,因此第一个孔洞传入 1,第二个传入 2。返回值是一个 LineString,可以再用 ST_AsText() 转成便于阅读的 WKT。

-- N=1 表示第一个内部环;它不是外环,外环不参与这个编号
SELECT ST_AsText(
  ST_InteriorRingN(ST_GeomFromText(@poly_two_holes), 1)
) AS first_hole_ring;

-- N=2 表示第二个内部环,返回同样是 LineString 形态的边界
SELECT ST_AsText(
  ST_InteriorRingN(ST_GeomFromText(@poly_two_holes), 2)
) AS second_hole_ring;

如果业务字段里的“第一个环”指的是整个 WKT 的第一个环,就要特别注意:那个环是外环;而 ST_InteriorRingN() 的 N=1 指第一个内部环。两套编号不要混用。

外环与从 1 开始的内部环编号以及 ST_InteriorRingN 返回 LineString 的说明图
图2:外环、内部环编号、ST_InteriorRingN 与输入边界的静态关系图,不是 MySQL 界面截图。

兼容坑:NULL、空几何和格式错误要分开看

MySQL 手册对这一组 Polygon 属性函数给出了通用输入规则。把这些情况分开处理,排查时比只盯着返回的数字更可靠。

输入情况应关注的表现写查询时的含义
参数为 NULL返回 NULL不要把 NULL 自动当成 0;它可能表示没有输入对象。
几何对象为空返回 NULL空几何与“有一个没有孔洞的 Polygon”不是同一条数据语义。
几何语法不完整可能出现 ER_GIS_INVALID_DATA先检查 WKT 的括号、环闭合和坐标表达。
SRS 未定义可能出现 ER_SRS_NOT_FOUND使用带 SRS 的数据时,要让空间参考标识能够被 MySQL 识别。
-- NULL 会沿着函数结果传递,报表层需要决定如何展示它
SELECT ST_NumInteriorRing(NULL) AS hole_count;

-- 空几何也不应直接解释为“0 个孔洞”
SELECT ST_NumInteriorRing(ST_GeomFromText('GEOMETRYCOLLECTION EMPTY')) AS hole_count;

此外,本文标题讨论的是 Polygon 的内部环计数。若列中存的是 MultiPolygon,不能只因为名字相似就假设函数会自动把每个组成多边形的孔洞相加;应先依据实际数据类型选择对应的拆分或业务聚合方案。

完整片段:统计并读取第一个孔洞

如果页面既要显示孔洞数量,又要在详情页读取第一个孔洞的边界,可以把两个动作放在同一组查询中。这里仍然只展示函数关系,未把示例当作线上执行结果。

-- 统一准备一个包含两个内部环的 Polygon
SET @poly = 'POLYGON((0 0,12 0,12 12,0 12,0 0),
  (2 2,2 4,4 4,4 2,2 2),
  (7 7,7 10,10 10,10 7,7 7))';

-- 数量字段用于摘要,指定内部环用于详情;两个函数的 N 规则要保持一致
SELECT
  ST_NumInteriorRing(ST_GeomFromText(@poly)) AS hole_count,
  ST_AsText(ST_InteriorRingN(ST_GeomFromText(@poly), 1)) AS first_hole_ring;

落地时可以按下面的顺序检查:

  1. 确认数据确实是 Polygon,并把外环与内部环的语义分开。
  2. 用 ST_NumInteriorRing() 得到孔洞数量;数量为 0 只表示没有内部环。
  3. 需要具体边界时,用从 1 开始的 ST_InteriorRingN() 读取指定内部环。
  4. 遇到 NULL、空几何或错误时,保留原始状态,不要统一改写成数字 0。

常见追问

ST_NumInteriorRing 和 ST_NumInteriorRings 有什么区别?

MySQL 8.4 手册将两者并列为返回 Polygon 内部环数量的函数名。一个是单数形式,一个是复数形式,按团队可读性选择即可。

外环会不会被 ST_NumInteriorRing 统计进去?

不会。它统计的是内部环,也就是通常所说的多边形孔洞;外环只是 Polygon 的外部边界。

怎样读取第二个孔洞的坐标?

用 ST_InteriorRingN(poly, 2) 取得第二个内部环,再用 ST_AsText() 转成 WKT。编号从 1 开始,不要传 0。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>