我有一个充满二维数据的数据库- map 上的点。每个记录都有一个几何类型的字段。我需要做的就是将一个点传递给存储过程,该存储过程返回k个最近的点(k也将传递给sproc,但这很容易)。我在http://blogs.msdn.com/isaac/archive/2008/10/23/nearest-neighbors.aspx处找到了一个查询,该查询获取了最近的单个邻居,但是我不知道如何扩展它以找到k个最近的邻居。
这是当前查询-T
是表,g
是geometry字段,@x
是要搜索的点,Numbers
是具有1到n的整数的表:
DECLARE @start FLOAT = 1000;
WITH NearestPoints AS
(
SELECT TOP(1) WITH TIES *, T.g.STDistance(@x) AS dist
FROM Numbers JOIN T WITH(INDEX(spatial_index))
ON T.g.STDistance(@x) < @start*POWER(2,Numbers.n)
ORDER BY n
)
SELECT TOP(1) * FROM NearestPoints
ORDER BY n, dist
内部查询选择最近的非空区域,然后外部查询从该区域中选择最靠前的结果。外部查询可以轻松更改为(例如)
SELECT TOP(20)
,但是如果最近的区域仅包含一个结果,则您将无法执行该操作。我认为我可能需要递归搜索包含k条记录的第一个区域,但不使用表变量(这将导致维护问题,因为您必须创建表结构并且易于更改-字段很多),我看不出来
最佳答案
如果从内部查询中删除TOP (1) WITH TIES
并将外部查询设置为返回前k行,会发生什么情况?
我也想知道这项修正案是否有帮助。它应该比使用TOP
更有效:
DECLARE @start FLOAT = 1000
,@k INT = 20
,@p FLOAT = 2;
WITH NearestPoints AS
(
SELECT *
,T.g.STDistance(@x) AS dist
,ROW_NUMBER() OVER (ORDER BY T.g.STDistance(@x)) AS rn
FROM Numbers
JOIN T WITH(INDEX(spatial_index))
ON T.g.STDistance(@x) < @start*POWER(@p,Numbers.n)
AND (Numbers.n - 1 = 0
OR T.g.STDistance(@x) >= @start*POWER(@p,Numbers.n - 1)
)
)
SELECT *
FROM NearestPoints
WHERE rn <= @k;
注意:未经测试-我无法在此处访问SQL 2008。
关于sql - 如何扩展此SQL查询以找到k个最近的邻居?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2522948/