3

私はc#とTSQLの例の両方でHarversine式の実装を持っています。サーバー側で数式を実装するのに最適な方法がわからないため、Linqクエリ内で数式を使用できます。

理想的には、ローカル数式をサーバー上の関数にリンクするだけです。したがって、「SQLへの変換なし」エラーを回避し、すべてを素晴らしくシームレスにします。

明らかに、問題に関するあらゆる見解が役立ちます。

SQL2008の地理タイプを知っています。ただし、私が取り組んでいるコードベースは、すでにSQLへのLinqに依存しています。これは、価値があるよりも手間がかかると思います。

ありがとう

4

2 に答える 2

5

100% SQL を使用して計算を行うのが最善の方法であり、単純に距離が既に入力されているテーブルを取得しないのはなぜですか?

既存の回答から

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

そして次のように使用されます:

var table = from r in db.VenuePostCodes 
            select new {
                lat = r.Latitude,
                lng = r.Longitude,
                name = r.Name,
                distance = db.udf_Haversine(
                                  r.Latitude,r.Longitude,
                                  r.Latitude,r.Longitude2)
            };

しかし、最良の方法は常にすべてを SQL 上に置くことです。これにより、ホスティング サーバーが行うことが少なくなり、単純に VIEW を SQL に追加してそのビューを呼び出すことができます。想像してみましょう。

SELECT 
   latitude, longitude, name, latitude1, longitude2, postcode, 
   udf_Haversine(latitude, longitude, latitude2, longitude2) AS distance 
FROM 
   venuepostcodes
ORDER BY 
   distance

LINQ を使用してそのビューを直接呼び出します。

于 2012-06-06T17:32:44.870 に答える
0

@balexandreの答えは素晴らしいですが、提供されたSQL関数には満足できませんでした(コメントが不足している、面白いコメントアウトされた定数がある、マイルですか?KM?など...)

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 = PI() / 180, -- Degrees to radians const
        @R = 6371 -- Radius of Earth in KM

    SELECT 
        @rlat1 = @lat1 * @DtoR,
        @rlong1 = @long1 * @DtoR,
        @rlat2 = @lat2 * @DtoR,
        @rlong2 = @long2 * @DtoR

    SELECT 
        @dlat = @rlat1 - @rlat2,
        @dlon = @rlong1 - @rlong2

    SELECT @a = SIN(@dlat / 2) * SIN(@dlat / 2) +
                SIN(@dlon / 2) * SIN(@dlon / 2) * COS(@rlat2) * COS(@rlat1)

    SELECT @c = 2 * atn2(sqrt(@a), sqrt(1 - @a))
    SELECT @d = @R * @c -- Final distance in KM

    SELECT @d = @d * 0.621371192 -- Final distance in miles

RETURN @d 
END

ここから取得した JavaScript 実装から変換され、最後にマイルに変換されます。

// Converted from JavaScript implementation:
// http://www.movable-type.co.uk/scripts/latlong.html

var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var lat1 = lat1.toRad();
var lat2 = lat2.toRad();

var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
var d = R * c;
于 2013-09-18T17:16:54.640 に答える