为什么SQL Server中geometry类型求线最近点的查询返回空几何?
问题原因
该问题由两个核心因素共同导致:
- 浮点数精度误差:
STDistance()计算点到线的距离时返回双精度浮点数,本身存在极小的精度损失,使用该距离作为STBuffer()的半径时,很容易出现理论上刚好相切的缓冲区,实际计算出的半径比真实距离略小的情况,导致缓冲区和线要素没有交集,最终返回空集合。 - STBuffer的近似实现逻辑:SQL Server的
STBuffer()为了保证性能,不会严格按照数学定义生成完美圆形缓冲区,而是用多边形拟合近似圆形,这种近似计算会进一步放大精度误差,在你测试的p2场景下,近似后的缓冲区刚好没有覆盖到线要素,就出现了空结果的问题。
修复方案
不要使用STBuffer()+STIntersection的逻辑计算最近点,SQL Server 2012及以上版本已经提供了专门的STClosestPoint()方法,直接调用即可完全避免精度问题:
declare @line geometry = 'LINESTRING(0 0, 10 10)' declare @p1 geometry = 'POINT(3 2)' declare @p2 geometry = 'POINT(3 1)' select @p1.STClosestPoint(@line).ToString() select @p2.STClosestPoint(@line).ToString()
如果需要兼容旧版本必须使用原逻辑,可以给缓冲区半径增加一个极小的容错偏移值(例如1e-8)抵消精度误差即可:
select @p1.STBuffer(@p1.STDistance(@line) + 1e-8).STIntersection(@line).ToString() select @p2.STBuffer(@p2.STDistance(@line) + 1e-8).STIntersection(@line).ToString()
内容的提问来源于stack exchange,提问作者TrevorJ
相关产品推荐
相关产品推荐

