表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社区是否有任何关于如何更好地优化这样的东西的额外想法。
尝试交叉申请:
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
我玩了一个新的选项,我认为这是我得到的最快的计算 - 大约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米内的任何数据。然后,我可以传递更新语句来计算更易于管理的数据集上的距离。