计算两点之间的距离(纬度,经度)

Wal*_*ler 82 sql t-sql sql-server math sql-server-2008-r2

我试图计算地图上两个位置之间的距离.我存储了我的数据:经度,纬度,X POS,Y POS.

我以前使用过下面的代码片段.

DECLARE @orig_lat DECIMAL
DECLARE @orig_lng DECIMAL
SET @orig_lat=53.381538 set @orig_lng=-1.463526
SELECT *,
    3956 * 2 * ASIN(
          SQRT( POWER(SIN((@orig_lat - abs(dest.Latitude)) * pi()/180 / 2), 2) 
              + COS(@orig_lng * pi()/180 ) * COS(abs(dest.Latitude) * pi()/180)  
              * POWER(SIN((@orig_lng - dest.Longitude) * pi()/180 / 2), 2) )) 
          AS distance
--INTO #includeDistances
FROM #orig dest
Run Code Online (Sandbox Code Playgroud)

不过我不相信这个数据,它似乎给出了稍微不准确的结果.

一些示例数据,以备您需要时使用

Latitude        Longitude     Distance 
53.429108       -2.500953     85.2981833133896
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮我解决我的代码,我不介意你是否想要修复我已经拥有的东西,如果你有一种新方法可以实现这一点,那就太棒了.

请说明您的结果所在的计量单位.

Aak*_*shM 119

由于您使用的是SQL Server 2008,因此您可以使用geography适用于此类数据的数据类型:

DECLARE @source geography = 'POINT(0 51.5)'
DECLARE @target geography = 'POINT(-3 56)'

SELECT @source.STDistance(@target)
Run Code Online (Sandbox Code Playgroud)

----------------------
538404.100197555

(1 row(s) affected)
Run Code Online (Sandbox Code Playgroud)

告诉我们它离伦敦(近)爱丁堡(近)约538公里.

当然,首先要学习一些知识,但是一旦你知道它,就比实施你自己的Haversine计算容易得多; 再加上你获得了很多功能.


如果要保留现有数据结构,仍可以使用以下方法STDistance构建合适的geography实例Point:

DECLARE @orig_lat DECIMAL(12, 9)
DECLARE @orig_lng DECIMAL(12, 9)
SET @orig_lat=53.381538 set @orig_lng=-1.463526

DECLARE @orig geography = geography::Point(@orig_lat, @orig_lng, 4326);

SELECT *,
    @orig.STDistance(geography::Point(dest.Latitude, dest.Longitude, 4326)) 
       AS distance
--INTO #includeDistances
FROM #orig dest
Run Code Online (Sandbox Code Playgroud)

  • @nezam no - [Prime Meridian]西部的经度将为负数(http://en.wikipedia.org/wiki/Prime_meridian),而东部的地方则为正数 (6认同)
  • 仅供参考:POINT(经度纬度),而geoge :: Point(经纬度,纬度4326) (3认同)

Dur*_*n.H 39

以下功能给出了两英里的地理坐标之间的距离

create function [dbo].[fnCalcDistanceMiles] (@Lat1 decimal(8,4), @Long1 decimal(8,4), @Lat2 decimal(8,4), @Long2 decimal(8,4))
returns decimal (8,4) as
begin
declare @d decimal(28,10)
-- Convert to radians
set @Lat1 = @Lat1 / 57.2958
set @Long1 = @Long1 / 57.2958
set @Lat2 = @Lat2 / 57.2958
set @Long2 = @Long2 / 57.2958
-- Calc distance
set @d = (Sin(@Lat1) * Sin(@Lat2)) + (Cos(@Lat1) * Cos(@Lat2) * Cos(@Long2 - @Long1))
-- Convert to miles
if @d <> 0
begin
set @d = 3958.75 * Atan(Sqrt(1 - power(@d, 2)) / @d);
end
return @d
end 
Run Code Online (Sandbox Code Playgroud)

以下功能给出了以千米为单位的两个地理坐标之间的距离

CREATE FUNCTION dbo.fnCalcDistanceKM(@lat1 FLOAT, @lat2 FLOAT, @lon1 FLOAT, @lon2 FLOAT)
RETURNS FLOAT 
AS
BEGIN

    RETURN ACOS(SIN(PI()*@lat1/180.0)*SIN(PI()*@lat2/180.0)+COS(PI()*@lat1/180.0)*COS(PI()*@lat2/180.0)*COS(PI()*@lon2/180.0-PI()*@lon1/180.0))*6371
END
Run Code Online (Sandbox Code Playgroud)

下面的函数 使用在sql server 2008中引入的Geography数据类型,以千米为单位给出两个地理坐标之间的距离

DECLARE @g geography;
DECLARE @h geography;
SET @g = geography::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656)', 4326);
SET @h = geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326);
SELECT @g.STDistance(@h);
Run Code Online (Sandbox Code Playgroud)

用法:

select [dbo].[fnCalcDistanceKM](13.077085,80.262675,13.065701,80.258916)
Run Code Online (Sandbox Code Playgroud)

参考: Ref1,Ref2

  • 我需要根据与邮政编码的距离排序的各种事件的邮政编码对 35K 邮政编码进行距离计算。使用地理数据类型进行计算的坐标列表太大。当我改用上面基于单线触发函数的解决方案时,它运行得更快。因此,仅使用地理类型来计算距离似乎很昂贵。买家当心。 (2认同)
  • 如果我们比较 2 个相等的点,“两个地理坐标之间的距离(以公里为单位)”函数会失败,它会给出错误“发生了无效的浮点运算” (2认同)
  • 这很好,但不适用于短距离,因为“decimal(8,4)”不能提供足够的精度。 (2认同)

Sta*_*nko 6

微软似乎侵入了所有其他受访者的大脑,并让他们编写尽可能复杂的解决方案。这是没有任何其他函数/声明语句的最简单方法:

SELECT geography::Point(LATITUDE_1, LONGITUDE_1, 4326).STDistance(geography::Point(LATITUDE_2, LONGITUDE_2, 4326))

简单地替换为您的数据,而不是LATITUDE_1LONGITUDE_1LATITUDE_2LONGITUDE_2如:

SELECT geography::Point(53.429108, -2.500953, 4326).STDistance(geography::Point(c.Latitude, c.Longitude, 4326))
from coordinates c
Run Code Online (Sandbox Code Playgroud)

  • 供参考:STDistance() 以定义地理数据的空间参考系统的线性度量单位返回距离。您使用的是 SRID 4326,这意味着 STDistance() 以米为单位返回距离。 (2认同)

Ada*_*Dev 5

当您使用 SQL 2008 或更高版本时,我建议检查GEOGRAPHY数据类型。SQL 内置了对地理空间查询的支持。

例如,您的表格中有一个 GEOGRAPHY 类型的列,其中将填充坐标的地理空间表示(请查看上面链接的 MSDN 参考示例)。然后,该数据类型公开允许您执行一系列地理空间查询的方法(例如查找两点之间的距离)


Fat*_* K. 5

Create Function [dbo].[DistanceKM] 
( 
      @Lat1 Float(18),  
      @Lat2 Float(18), 
      @Long1 Float(18), 
      @Long2 Float(18)
)
Returns Float(18)
AS
Begin
      Declare @R Float(8); 
      Declare @dLat Float(18); 
      Declare @dLon Float(18); 
      Declare @a Float(18); 
      Declare @c Float(18); 
      Declare @d Float(18);
      Set @R =  6367.45
            --Miles 3956.55  
            --Kilometers 6367.45 
            --Feet 20890584 
            --Meters 6367450 


      Set @dLat = Radians(@lat2 - @lat1);
      Set @dLon = Radians(@long2 - @long1);
      Set @a = Sin(@dLat / 2)  
                 * Sin(@dLat / 2)  
                 + Cos(Radians(@lat1)) 
                 * Cos(Radians(@lat2))  
                 * Sin(@dLon / 2)  
                 * Sin(@dLon / 2); 
      Set @c = 2 * Asin(Min(Sqrt(@a))); 

      Set @d = @R * @c; 
      Return @d; 

End
GO
Run Code Online (Sandbox Code Playgroud)

用法:

选择 dbo.DistanceKM(37.848832506474, 37.848732506474, 27.83935546875, 27.83905546875)

输出:

0,02849639

您可以使用带注释的浮点数更改 @R 参数。