在设定半径内计算和返回表A中表B中最接近项的最快方法是什么

问题描述 投票:2回答:2

表1中有一个非常大量的纬度/经度坐标,以及表2.例如,假设两个表中有100,000个坐标。我需要从表1中返回表2中最接近的一对坐标,只要它们在表1中的每个唯一项目的设定最小距离(例如,100米)内(最多100,000个项目,但随后剔除)到100米是我的预期输出)。

我对MSSQL的几何和地理部分非常熟悉,并且传统上会使用以下内容来处理以下内容:

Select
Table1ID = T1.ID,
Table2ID = T2.ID,
Distance = T1.PointGeog.STDistance(T2.PointGeog),
Keep = 0
into #Distance 
From #Table1 T1
   cross join #Table2 T2
where T1.PointGeog.STDistance(T2.PointGeog) <= 100

这将返回Table2中距离Table1 100米范围内的所有项目

然后,为了限制只有最近的项目,我可以:

Update #Distance
 set Keep = 1
from #Distance D 
   inner join 
   (select shortestDist = min(Distance), Table1ID from #Distance GROUP BY 
    Table1ID) A
    on A.ID = D.Table1ID and A.shortestDist = D.Distance

然后删除保持<> 1的任何内容

这是有效的,但它绝对永远。交叉连接创建了SQL需要处理的大量计算,这导致MSSQL 2016上的约9分钟查询。我可以限制表1和表2中与某些条件进行比较的部分的范围,但实际上并非如此许多。我真的不确定如何让这个过程更快。最终,我只需要:最近的项目,从T2到T1的距离。

我已经玩了几个不同的解决方案,但我想看看SO社区是否有任何关于如何更好地优化这样的东西的额外想法。

sql tsql gis spatial
2个回答
0
投票

尝试交叉申请:

SELECT 
    T1.ID, TT2.ID, T1.PointGeog.STDistance(TT2.PointGeog)
FROM #Table1 as T1
CROSS APPLY (SELECT TOP 1 T2.ID, T2.PointGeog 
  FROM #Table2 as T2
  WHERE T1.PointGeog.STDistance(T2.PointGeog) <= 100
  ORDER BY T1.PointGeog.STDistance(T2.PointGeog) ASC) as TT2

0
投票

我玩了一个新的选项,我认为这是我得到的最快的计算 - 大约3分钟。

我将Table1更改为:

select
ID,
PointGeog,
Buffer = PointGeom.STBuffer(8.997741566866716e-4)
into #Table1

缓冲区为100/111139(将度数转换为米)

然后

if object_id('tempdb.dbo.#Distance') is not null
drop table #Distance 
Select 
T1ID = T1.ID,
T1Geog = T1.PointGeog,
T2ID = T2.ID,
T2Geog = T2.PointGeog,
DistanceMeters = cast(null as float),
DistanceMiles = cast(null as float),
Keep = 0
Into #Distance
From #Table1 T1
    cross join #Table2 T2
Where T1.Buffer.STIntersects(T2.PointGeom) = 1

它不计算距离,但首先将数据集剔除到100米内的任何数据。然后,我可以传递更新语句来计算更易于管理的数据集上的距离。

© www.soinside.com 2019 - 2024. All rights reserved.