SQL Server 使用 Haversine 公式计算经纬度距离

慢慢来
慢慢来
发布时间:2026-10-14 | 4人浏览过
原创

在基于位置的服务(LBS)开发中,经常需要根据用户的经纬度坐标快速筛选出附近的地点或计算两点间的直线距离。由于 SQL Server 标准版本未直接提供高精度的地理空间聚合函数,我们可以通过创建一个内置的标量值函数,结合球面三角学中的 Haversine 公式来实现这一功能。

结果与目标

实现一个名为 [dbo].[fnGetDistance] 的 SQL Server 函数,输入四个参数:@LatBegin(起点纬度)、@LngBegin(起点经度)、@LatEnd(终点纬度)和 @LngEnd(终点经度),输出两点之间的地表距离(单位:千米)。

准备条件

  • 拥有 SQL Server 数据库的写入权限或相应的存储过程执行权限。
  • 理解基本的 T-SQL 语法,包括变量声明、赋值和控制流。
  • 确认坐标系数据格式为标准 WGS84 经纬度(例如:纬度 39.9042, 经度 116.4074)。

真实操作顺序

第1步:定义地球半径常量

目的:确定用于计算的地球平均半径,以提高计算精度。通常取赤道半径近似值。

在 T-SQL 脚本中,设置全局使用的地球半径变量:

-- 地球半径(千米),采用常用近似值
DECLARE @EARTH_RADIUS REAL
SET @EARTH_RADIUS = 6378.137

第2步:转换角度单位为弧度

目的:Haversine 公式需要使用弧度进行三角函数运算,因此需要将输入的十进制经纬度转换为弧度。

关键计算公式如下:

  • 弧度 = 度数 × PI() / 180.0
  • 分别计算起终点的纬度弧度和经度差弧度。

第3步:应用 Haversine 公式计算距离

目的:根据球面几何原理,计算两点间的大圆距离。这是核心算法部分。

Haversine 公式的具体实现逻辑:

-- 计算中间变量:纬度差弧度与经度差弧度
SET @RadLatDiff = @RadLatBegin - @RadLatEnd
SET @RadLngDiff = @LngBegin * PI() / 180.0 - @LngEnd * PI() / 180.0

-- 应用 Haversine 核心公式
SET @Distance = 2 * ASIN(
    SQRT(
        POWER(SIN(@RadLatDiff / 2), 2) +
        COS(@RadLatBegin) * COS(@RadLatEnd) *
        POWER(SIN(@RadLngDiff / 2), 2)
    )
)

-- 将弧度距离转换为实际距离(千米)
SET @Distance = @Distance * @EARTH_RADIUS

第4步:封装为 SQL Server 函数

目的:将上述逻辑打包为可复用的数据库对象,方便在查询语句中直接调用。

完整的函数创建代码如下,请根据你的实际需求调整架构名(默认为 [dbo]):

-- 创建经纬度距离计算函数
CREATE FUNCTION [dbo].[fnGetDistance] (
    @LatBegin REAL,   -- 开始纬度 (Latitude)
    @LngBegin REAL,   -- 开始经度 (Longitude)
    @LatEnd REAL,     -- 结束纬度
    @LngEnd REAL      -- 结束经度
)
RETURNS FLOAT
AS
BEGIN
    DECLARE @Distance REAL
    DECLARE @EARTH_RADIUS REAL
    SET @EARTH_RADIUS = 6378.137 -- 地球半径(千米)

    DECLARE @RadLatBegin REAL,
            @RadLatEnd REAL,
            @RadLatDiff REAL,
            @RadLngDiff REAL

    -- 经纬度转为弧度
    SET @RadLatBegin = @LatBegin * PI() / 180.0
    SET @RadLatEnd = @LatEnd * PI() / 180.0
    
    -- 计算差值
    SET @RadLatDiff = @RadLatBegin - @RadLatEnd
    SET @RadLngDiff = @LngBegin * PI() / 180.0 - @LngEnd * PI() / 180.0

    -- 计算距离
    SET @Distance = 2 * ASIN(
        SQRT(
            POWER(SIN(@RadLatDiff / 2), 2) +
            COS(@RadLatBegin) * COS(@RadLatEnd) *
            POWER(SIN(@RadLngDiff / 2), 2)
        )
    )
    
    SET @Distance = @Distance * @EARTH_RADIUS
    
    -- 如需保留更多小数位,可取消下方注释并调整乘数
    -- SET @Distance = Round(@Distance * 10000) / 10000

    RETURN @Distance
END;

完成判断

  1. 在 SSMS 中执行上述 CREATE FUNCTION 脚本,无报错信息即表示函数创建成功。
  2. 可以使用 SELECT 语句验证结果:
    SELECT dbo.fnGetDistance(39.9042, 116.4074, 31.2304, 121.4737) AS DistanceBetween_BJ_SH;
    
    预期结果应接近北京到上海的直线距离(约 1000 千米左右)。

原文有依据的排错

注意经纬度参数顺序: 很多开发者容易混淆纬度(Latitude)和经度(Longitude)。在上述代码中,前两个参数代表“起点”,后两个参数代表“终点”。务必确保传入的是 (纬度, 经度) 而非 (经度, 纬度),否则计算结果将完全错误。

性能考量: 对于包含数万条记录的表,在每一行都调用此标量函数可能会导致严重的性能瓶颈。如果需要在大数据集中进行“附近搜索”,建议结合空间索引(Spatial Index)或使用 SQL Server 2008+ 原生支持的 geography 数据类型,其自带的方法(如 .STDistance())性能更为优越。

简要总结

通过上述 T-SQL 函数,我们可以低成本地在任何版本的 SQL Server 中实现高精度的经纬度距离计算。掌握 Haversine 公式的原理不仅有助于解决具体的编程问题,也为处理更复杂的地理空间数据分析奠定了基础。以上就是基于 SQL Server 根据地图经纬度计算距离差的详细内容,更多关于 SQL Server 地理信息查询的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表