T-SQL:CROSS JOIN 和 STDistance 查找最近点

问题描述 投票:0回答:1

我有两张桌子,上面有沃尔玛地点,我想知道一张桌子上的哪家沃尔玛距离另一家地点的沃尔玛最近。

如果可能的话,这将是结果:

Source        ClosestToSource       DistanceInMeters
-----------------------------------------------------
Walmart1      Walmart8              2637.37
Walmart2      Walmart5              2047.19
Walmart3      Walmart8              1191.31
Walmart4      Walmart7              3340.33

这基本上是说,@Source中距离

Walmart1
最近的沃尔玛是@Dest中的
Walmart8

IF OBJECT_ID('dbo.WSource', 'U') IS NOT NULL 
    DROP TABLE dbo.WSource; 

IF OBJECT_ID('dbo.WDest', 'U') IS NOT NULL 
    DROP TABLE dbo.WDest; 

CREATE TABLE dbo.WSource
(
    Id int IDENTITY,
    StoreName varchar(15),
    Lat float,
    Lon float,
    GeoLocation geography
)

CREATE TABLE WDest
(
    Id int IDENTITY,
    StoreName varchar(15),
    Lat float,
    Lon float,
    GeoLocation geography
)

INSERT INTO WSource (StoreName, Lat, Lon)
select 'Walmart1', 28.064924, -81.652854 union
select 'Walmart2', 28.073512, -81.655092 union
select 'Walmart3', 28.063939, -81.665558 union
select 'Walmart4', 28.061616, -81.630152

update WSource
set geolocation = geography::STPointFromText('POINT(' + CAST(Lon AS VARCHAR(20)) + ' ' + 
                    CAST(Lat AS VARCHAR(20)) + ')', 4326)


insert into WDest (StoreName, Lat, Lon)
select 'Walmart5', 28.078024, -81.675264 union
select 'Walmart6', 28.079128, -81.693943 union
select 'Walmart7', 28.089832, -81.642243 union
select 'Walmart8', 28.062409, -81.677583

update WDest
set geolocation = geography::STPointFromText('POINT(' + CAST(Lon AS VARCHAR(20)) + ' ' + 
                    CAST(Lat AS VARCHAR(20)) + ')', 4326)

SELECT WSource.geolocation.STDistance(WDest.geolocation)
FROM WSource
CROSS JOIN WDest

这显示了从一个位置到另一个位置的所有距离,但这就是我陷入困境的地方。我正在考虑使用

RANK()
函数,但我不确定如何实现。

根据上面的结果,最接近Walmart2的是Walmart5,但不确定如何实现。

或者也许有更好的方法?

t-sql sql-server-2012
1个回答
1
投票

一个选项是

APPLY
TOP (1)

SELECT
  WSource.StoreName AS Source,
  WDest.StoreName AS ClosestToSource,
  WDest.DistanceToSource
FROM WSource
CROSS APPLY (
    SELECT TOP (1)
      WDest.*,
      WSource.geolocation.STDistance(WDest.geolocation) AS DistanceToSource
    FROM WDest
    ORDER BY DistanceToSource
) WDest;

您还可以使用排名功能

SELECT
  w.*
FROM (
    SELECT
      WSource.StoreName AS Source,
      WDest.StoreName AS ClosestToSource,
      WSource.geolocation.STDistance(WDest.geolocation) AS DistanceToSource,
      ROW_NUMBER() OVER (PARTITION BY WSource.Id ORDER BY WSource.geolocation.STDistance(WDest.geolocation)) AS rn
    FROM WSource
    CROSS JOIN WDest
) w
WHERE w.rn = 1;

性能差异可能取决于您是否有支持的空间索引:如果有,前者的性能会非常好,但如果没有,则性能会很差。

您可能还想检查计算从源到目标的距离是否更快,反之亦然。

db<>小提琴

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