【问题标题】:Haversine formula using SQL server to find closest venue - vb.netHaversine 公式使用 SQL 服务器查找最近的地点 - vb.net
【发布时间】:2011-07-18 18:17:10
【问题描述】:

我正在从表单中获取邮政编码。然后我可以将此邮政编码转换为 lng,lat 坐标,因为我已将它们存储在表格中。

SELECT lng, lat from postcodeLngLat WHERE postcode = 'CV1'

我有另一张表,用于存储所选场地的 lng、lat。

SELECT v.lat, v.lng, v.name, p.lat, p.lng, p.postcode, 'HAVERSINE' AS distance FROM venuepostcodes v, postcodeLngLat p WHERE p.outcode = 'CB6' ORDER BY distance

我要做的是创建一个数据网格,显示每个场地与邮政编码(在本例中为 CV1)的距离。我知道 Haversine 公式应该做我想要实现的目标,但我不知道应该从哪里开始将它合并到我的查询中。我认为公式需要放在我在上面的查询中输入'HAVERSINE' 的位置。

有什么想法吗?

编辑

SELECT o.outcode AS lead_postcode, v.venue_name, 6371.0E * ( 2.0E *asin(case when 1.0E < (sqrt(square(sin(((RADIANS(CAST(o.lat AS FLOAT)))-(RADIANS(CAST(v.lat AS FLOAT))))/2.0E)) + (cos(RADIANS(CAST(v.lat AS FLOAT))) * cos(RADIANS(CAST(o.lat AS FLOAT))) * square(sin(((RADIANS(CAST(o.lng AS FLOAT)))-(RADIANS(CAST(v.lng AS FLOAT))))/2.0E))))) then 1.0E else (sqrt(square(sin(((RADIANS(CAST(o.lat AS FLOAT)))-(RADIANS(CAST(v.lat AS FLOAT))))/2.0E)) + (cos(RADIANS(CAST(v.lat AS FLOAT))) * cos(RADIANS(CAST(o.lat AS FLOAT))) * square(sin(((RADIANS(CAST(o.lng AS FLOAT)))-(RADIANS(CAST(v.lng AS FLOAT))))/2.0E))))) end )) AS distance FROM venuepostcodes v, outcodepostcodes o WHERE o.outcode = 'CB6' ORDER BY distance

【问题讨论】:

    标签: sql sql-server haversine


    【解决方案1】:

    我认为你最好把它放在一个 UDF 中并在你的查询中使用它:

    SELECT v.lat, v.lng, v.name, p.lat, p.lng, p.postcode, udf_Haversine(v.lat, v.lng, p.lat, p.lng) AS distance FROM venuepostcodes v, postcodeLngLat p WHERE p.outcode = 'CB6' ORDER BY distance
    
    create function dbo.udf_Haversine(@lat1 float, @long1 float, @lat2 float, @long2 float) returns float begin
            declare @dlon float, @dlat float, @rlat1 float, @rlat2 float, @rlong1 float, @rlong2 float, @a float, @c float, @R float, @d float, @DtoR float
    
            select @DtoR = 0.017453293
            select @R = 3937 --3976
    
            select 
                @rlat1 = @lat1 * @DtoR,
                @rlong1 = @long1 * @DtoR,
                @rlat2 = @lat2 * @DtoR,
                @rlong2 = @long2 * @DtoR
    
            select 
                @dlon = @rlong1 - @rlong2,
                @dlat = @rlat1 - @rlat2
    
            select @a = power(sin(@dlat/2), 2) + cos(@rlat1) * cos(@rlat2) * power(sin(@dlon/2), 2)
            select @c = 2 * atn2(sqrt(@a), sqrt(1-@a))
            select @d = @R * @c
    
            return @d 
        end
    

    【讨论】:

    • 是否可以将其插入到我的 .net 页面上的 .vb 文件中,还是需要将该功能放在其他地方? - 再加上什么是“浮动”位?
    • 这里写的函数是SQL Server用户定义函数。您可以将其转换为 vb,但随后您必须将所有数据带回“客户端”进行计算。使用 SQL UDF,您可以执行诸如选择最接近的前 10 个并且仅将这 10 个的数据发送到“客户端”
    • @Tom - 我认为大卫是说要在 SQL Server 中创建一个函数。 UDF -> 用户定义函数。 (google.com/search?q=SQL+Server+UDF)
    • 另外,我刚刚注意到@R 附近的评论,可能想验证Haversine 公式是否100% 正确。
    • 好的,所以我接受你的想法肯定是正确的方法。但是,我确实使用以下添加到我原来问题中的代码重新创建了这个函数......谢谢
    【解决方案2】:

    或者,您也可以使用 SQL Server 2008 地理数据类型。如果您当前将经度/纬度作为 varchar() 存储在数据库中,则必须将它们存储为 geograpghy 数据类型,然后使用 STIntersects() 之类的函数来获取距离。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-13
      • 1970-01-01
      • 2012-06-10
      • 1970-01-01
      • 2015-02-26
      • 2014-04-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多