【问题标题】:SQL Server: how to find closest location?SQL Server:如何找到最近的位置?
【发布时间】:2014-01-17 18:03:33
【问题描述】:

我有两张桌子,Houses 和 Stores。两者都有纬度和经度字段。我需要为 Houses HouseId 和 StoreId 中的每条记录创建一个视图,其中 StoreId 是离房子最近的商店的 ID。我确实有一个函数CalculateDistance(float Long1,float Lat1,float Long2,float Lat2)。 但是我无法提出可以生成我需要的视图的查询。

谢谢。

【问题讨论】:

    标签: sql sql-server-2008 geo


    【解决方案1】:

    您可以在表格中创建Geography 行(地理代码)并从您的LatitudeLongitude 填充它:

    UPDATE [dbo].[MyTable]
       SET [Geocode] = geography::Point(Latitude, Longitude , 4326)
    GO
    

    然后从坐标查询最近的位置:

    DECLARE @g geography = 'POINT(-121.626 47.8315)';  
    SELECT TOP(1) Geocode.STDistance(@g), ShopId FROM MyTable
    ORDER BY Geocode.STDistance(@g);  
    

    它将返回距离您最近的坐标。

    【讨论】:

      【解决方案2】:

      来自我的一个应用程序的工作示例...您显然需要重新映射列和表。

      DECLARE @Lat float= -83.555
      DECLARE @Long float = 43.555
      SELECT TOP 100 ID, Abbr, Distance FROM 
      (
          SELECT NL.NodeLocationID AS ID, NL.NodeLocationAbbr AS Abbr, (ABS(NL.Latitude - @Lat) + ABS(NL.Longitude - @Long)) / 2 AS Distance 
          FROM NodeLocations AS NL
          WHERE (NL.Latitude IS NOT NULL) AND (NL.Longitude IS NOT NULL)
      ) AS D1 
      ORDER BY Distance
      

      下面查找与同一张表中其他项目最接近的项目(可以通过将 NL2 更改为另一个表来更改)。这可以找到最接近的项目,但是性能很糟糕,具体取决于您处理的记录数量。我建议您创建一个静态字段并通过后台进程计算每个字段。

      SELECT *
      FROM 
          (
          SELECT TOP 100 PERCENT *
              , ROW_NUMBER () OVER (PARTITION BY ID ORDER BY Distance ASC) AS Rnk
          FROM 
              (
                  SELECT NL.NodeLocationID AS ID, NL.NodeLocationAbbr AS Abbr
                      , NL2.NodeLocationID AS ID2, NL2.NodeLocationAbbr AS Abbr2
                      , (ABS(NL.Latitude - NL2.Latitude) + ABS(NL.Longitude - NL2.Longitude)) / 2 AS Distance 
                  FROM NodeLocations AS NL
                      JOIN NodeLocations AS NL2 ON NL.NodeLocationID<>NL2.NodeLocationID AND (ABS(NL.Latitude - NL2.Latitude) + ABS(NL.Longitude - NL2.Longitude)) / 2 <= 0.1
                  WHERE (NL.Latitude IS NOT NULL) AND (NL.Longitude IS NOT NULL)
                      AND (NL2.Latitude IS NOT NULL) AND (NL2.Longitude IS NOT NULL)
              ) AS D1 
          ) AS D2
      WHERE D2.Rnk=1
      

      【讨论】:

      • 不考虑地球的曲率或经纬度之间的差异等,但通常适用于地球上人口最多的地方。
      • 嗯,在我看来,这并不能满足我的需要。它只返回从不同位置到一个给定位置的距离。但我需要别的东西。
      • 我刚刚修改添加了另一个SQL。我的原始代码来自给定的现有点。
      • 谢谢达伦。但是您会看到,您的查询现在会找到彼此非常接近的位置。但是我需要为每个房子找到最近的商店,即使它实际上并不接近,即距离应该是 min(Distance)。
      • 是的,我让你上了那个。我没有类似的数据来做同样的想法,而且我正在操作的数据很大(这就是我添加距离限制的原因。但是该 SQL 返回到所有其他位置的最近位置(我只有“房屋” , 用你的话). 你应该能够用你的 "Stores" 表替换第二个 "NodeLocations", 将 Join 更改为 CROSS JOIN 而没有任何条件, 你将获得离每个位置最近的 Store. 很难处理在无法访问数据的情况下使用这种东西:),希望这个想法对您有所帮助
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-24
      • 2015-11-26
      • 2014-05-06
      • 1970-01-01
      • 2021-11-27
      • 1970-01-01
      • 2010-09-24
      相关资源
      最近更新 更多