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

我正在计算地图上两个位置之间的距离。 我已经存储在我的数据:经度,纬度,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 

然而,我不相信这些数据出来,似乎给了稍微不准确的结果。

一些示例数据,以防您需要

 Latitude Longitude Distance 53.429108 -2.500953 85.2981833133896 

任何人都可以帮我解决我的代码问题,如果你有一个新的方法来实现这个目标,我不介意你想解决我已经有的问题。

请说明你的结果是在什么度量单位。

由于您使用的是SQL Server 2008,因此您可以使用geography数据types,该数据types专门用于这种types的数据:

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

 ---------------------- 538404.100197555 (1 row(s) affected) 

告诉我们,从伦敦到(靠近)爱丁堡约538公里。

自然会有大量的学习要做,但是一旦你知道了,这比实现自己的Haversine计算要容易得多。 再加上你得到了很多的function。


如果你想保留你现有的数据结构,你仍然可以使用STDistance ,通过使用Point方法构build合适的geography实例:

 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 

下面的函数给出两个地理坐标之间的距离,以英里为单位

 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 

下面的函数给出了以公里为单位的两个地理坐标之间的距离

 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 

下面的函数使用在sql server 2008中引入的地理数据types给出了以公里为单位的两个地理坐标之间的距离

 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); 

用法:

 select [dbo].[fnCalcDistanceKM](13.077085,80.262675,13.065701,80.258916) 

参考: Ref1 , Ref2

在使用SQL 2008或更高版本时,我build议检查GEOGRAPHY数据types。 SQL已经构build了对地理空间查询的支持。

例如,在您的GEOGRAPHYtypes的表格中将会有一列填充坐标的地理空间表示(请参阅上面链接的MSDN参考资料)。 然后这个数据types暴露方法,允许你执行大量的地理空间查询(例如find2点之间的距离)

 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 

用法:

selectdbo.DistanceKM(37.848832506474,37.848732506474,27.83935546875,27.83905546875)

输出:

0,02849639

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