如何计算 SQL 服务器中多个源的 "Nearest Neighbour"?

How to calculate the "Nearest Neighbour" for multiple sources in SQL Server?

"Nearest Neighbour" 问题在处理空间数据时很常见。

在他们的文档中甚至有一些 nice, simple documentation 关于如何使用 MS Sql 服务器做到这一点!

我经常看到使用 1x 源 Lat/Long 并且 return 是 'x' 个最近邻 Lat/Long 的例子。很好...

例如

USE AdventureWorks2012  
GO  
DECLARE @g geography = 'POINT(-121.626 47.8315)';  
SELECT TOP(7) SpatialLocation.ToString(), City FROM Person.Address  
WHERE SpatialLocation.STDistance(@g) IS NOT NULL  
ORDER BY SpatialLocation.STDistance(@g);

在我的例子中,我有 多个 Lat/Long 个来源...并且对于每个来源,需要 return 'x' 个数最近的邻居。

这是我的架构

Table: SomeGeogBoundaries
LocationId INTEGER PRIMARY KEY (it's not an identity, but a PK & FK)
CentrePoint GEOGRAPHY

Index:
Spatial Index on CentrePoint column. [Geography || MEDIUM, MEDIUM, HIGH, HIGH]

示例数据:

LocationId | CP Lat/Long
1          | 10,10
2          | 11,11
3          | 20,20

..

所以对于这个 table 中的每个位置,我需要找到最近的..比如 5 个其他位置。

更新

到目前为止,似乎使用 CURSOR 是唯一的方法..但我愿意接受更多基于 set 的解决方案。

您需要在同一集合中找到最近的邻居吗?

SELECT *
FROM SomeGeogBoundaries as b
OUTER APPLY (
   SELECT TOP(5) CentrePoint
   FROM SomeGeogBoundaries as t
   WHERE t.CentrePoint.STInsersects(b.CentrePoint.STBuffer(100))
   ORDER by b.CentrePoint.STDistance(t.CentrePoint)
) AS nn

两个音符。

  1. outer apply 中的 where 子句将搜索限制为(在本例中)彼此相距 100 米以内的点(假设您正在使用一个 SRID,其本机计量单位是米)。这可能适合也可能不适合你。如果不是,则省略 where 子句。

  2. 我觉得这还是一个游标。不要自欺欺人地认为,仅仅因为没有 declare cursor 语句就可以看出数据库引擎有很多选择,只能遍历 table 并评估 apply对于每一行。