使用SQL Server的Haversine公式来查找最近的场馆 - VB.NET

3
我正在从一个表单中获取邮政编码。由于我在一个表中存储了这些编码的经纬度,因此可以将其转换为经纬度坐标。 SELECT lng, lat from postcodeLngLat WHERE postcode = 'CV1' 我还有另一个表格,其中存储了一些场馆的经纬度。 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
2个回答

10

我认为最好将其放入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文件中,还是需要将函数放在其他地方?此外,“float”这个位是什么意思? - Tom
这里所写的函数是一个SQL Server用户定义函数。你可以将它转换为VB,但那样你就必须将所有数据带回“客户端”进行计算。使用SQL UDF,您可以执行诸如选择最接近的前10个并仅将这些10个数据发送到“客户端”之类的操作。 - BlackICE
@Tom - 我认为David是在说要在SQL Server中创建一个函数。UDF -> 用户定义函数。(http://www.google.com/search?q=SQL+Server+UDF) - dana
另外,我刚刚注意到@R附近的注释,可能需要验证Haversine公式是否在其中100%正确。 - BlackICE
好的,我承认你的想法肯定是正确的方式。然而,我重新创建了这个函数,使用了以下代码添加到我的原始问题中...谢谢。 - Tom
非常感谢!拯救了我的一天! - Nitesh

3

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接