2017-04-05 94 views
1

使用空间数据时,“最近邻居”问题非常普遍。如何计算Sql Server中多个源的“最近邻居”?

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

我通常会看到使用1x源纬度/长度的示例,它会返回最近邻居纬度/长度的“x”数。细...

例如

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); 

在我的情况,我有多个纬度/长源...并为每个源,需要返回最近的邻居的“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 

.. 

所以在这个表中的foreach位置,我需要找到最接近..说5个其他位置。

UPDATE:

那么远,它看起来像使用CURSOR是唯一的方法..但我愿意更设置基础的解决方案......

回答

1

你需要找到同一组内最近的邻居?

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 applywhere条款是限制搜索(在这种情况下)100米的海誓山盟内的点(假设你正在使用的SRID的母语计量单位是米)。这可能会或可能不适合你。如果不是,只需省略where条款。

  2. 我认为这是仍然是游标。不要自欺欺人地想,仅仅因为有一个declare cursor声明可以看出db引擎有很多选择,只是遍历你的表并评估每行的apply

+0

甜!我第一次做了一个光标 - 花了1小时2分钟。然后用你的代码替换光标,花了58分钟。所以基本上是一样的。正如你所建议的,这可能是因为它是内部游标。另外,我假设(再次)我正在使用空间索引,因为我用't.CP.STDistance(b.CP)IS NOT NULL'替换了where子句以确保它使用空间索引。 –