一个位置的最小距离;一个点表与一组点 SQL 2012 相比

Rob*_*row 5 sql-server t-sql sql-server-2012 spatial

我试图找到找到一个点到点表的最小距离的最快方法。唯一需要注意的是,我试图找到最小距离的点表是 150K 单点。

或者更好地解释表 A 有 150K 行/点,表 B 1500 点。我想知道表 A 中的每一行与表 B 中列出的所有行的最小距离是多少。

我有一个进行距离计算的函数,作为表 A 的附加列。它只需要很长时间。表 B 有一个空间索引。

这就是我所拥有的:

select a.*, 
       dbo.fxn_distance(geography::STPointFromText('POINT(' + 
       CAST([Long] AS VARCHAR(20)) + ' ' + CAST([Lat] AS 
       VARCHAR(20)) +    ')', 4326)) as DistAway
from Table A a
Run Code Online (Sandbox Code Playgroud)

我的功能:

create function fxn_distance
(@pointTableA geography
)
returns float 
as 
begin

declare @distance float

select top 1 @distance = b.GeoLocation.STDistance(@pointTableA) 
from TableB b  
where geolocation.STDistance(@pointTableA) is not null
order by geolocation.STDistance(@pointTableA)

return @distance
end
Run Code Online (Sandbox Code Playgroud)

对不起,如果我完全是一个新手,我知道解决方案可能很简单,但我无法解决这个问题。所以希望澄清一下:我需要通过表 A 中每个点的经纬度,并查看最小距离与表 B 中每一行的比较,对于表 A 中的每一行。我关心实际距离是多少,但不是表 B 中的实际点。

任何帮助表示赞赏。

Han*_*non 3

如果将该函数转换为表值函数,可能会获得更好的性能。

在这里,我设置了测试台:

USE tempdb;
CREATE TABLE dbo.TableA
(
    LAT DECIMAL(10,5)
    , LON DECIMAL(10,5)
);

CREATE TABLE TableB
(
    Geolocation GEOGRAPHY NOT NULL
);
GO
Run Code Online (Sandbox Code Playgroud)

这是表值函数,它基本上是您的函数,只不过它返回一个表。

CREATE FUNCTION dbo.fxn_distance
(
    @pointTableA GEOGRAPHY
)
returns table
as return 
(
    SELECT TOP 1 Distance = b.GeoLocation.STDistance(@pointTableA) 
    FROM TableB b  
    WHERE geolocation.STDistance(@pointTableA) IS NOT NULL
    ORDER BY geolocation.STDistance(@pointTableA)
)
GO
Run Code Online (Sandbox Code Playgroud)

在两个表中分别插入一个简单的测试行:

INSERT INTO dbo.TableA(LAT, LON)
VALUES (49.0,170.0);

INSERT INTO dbo.TableB(Geolocation)
VALUES (geography::STGeomFromText(
    'LINESTRING(-122.360 47.656, -122.343 47.656)', 4326)
);
Run Code Online (Sandbox Code Playgroud)

使用内联 TVF 来确定最近点的查询:

SELECT a.*
    , d.Distance --This is the distance calculated by the TVF. 
FROM dbo.TableA a
CROSS APPLY dbo.fxn_distance(geography::STPointFromText('POINT(' + 
       CAST(A.LON AS VARCHAR(20)) + ' ' + CAST(A.LAT AS 
       VARCHAR(20)) + ')', 4326)) d ;
Run Code Online (Sandbox Code Playgroud)

  • TVF 对源表“TableA”中的每一行计算一次“Distance”,而在“select”子句中运行常规函数可能会导致每行对该函数进行多次计算。 (2认同)
  • @user3347256 SQL Server 中的 UDF 标量函数非常慢。如果 Max 刚刚提供的悬崖笔记版本还不足以满足您的好奇心,请将“标量 udf 性能”放入您最喜欢的搜索引擎中,您可以找到大量有关它的信息。 (2认同)