1

SQL Server 2005 Analysis Servicesを使用しており、MDX クエリ内で距離を計算しようとしています。これにより、現在の場所の近くにあるアイテムの数を取得できます。緯度と経度でディメンションを作成し、計算を行うための .NET アセンブリも作成しましたが、クエリですべてを解決するのに苦労しています。

半径 100 マイルのアイテムを検索するクエリは次のようになります。

select   FILTER([DimProducts].[Product].[Product],
         ZipCalculatorLib.GetDistance(43.474208, [Zip].[Latitude], 96.687689, [Zip].[Longitude]) < 100)  on rows,
        [Measures].[RowCount] on columns
from     MyCube;

そして、.NET の距離コードは次のようになります。

public static double GetDistance(double startLat, double endLat,
    double startLong, double endLong)
{
    return Math.Sqrt(Math.Pow(69.1 * (startLat - endLat), 2) + Math.Pow(Math.Cos(endLat / 57.3) * 69.1 * (startLong - endLong), 2));
}

ただし、そのクエリを実行すると、レコードがゼロになります。距離を 100 から 10000 に変更すると、半径 100 マイルの場合と同様のカウントが得られます。.NET クラスが平方根を実行していないように見えますが、そのコードを何度もテストしたところ、正しいように見えます。

問題を解決するためにどこを見ればよいかについて、誰か提案がありますか?

編集: 緯度と経度が GetDistance 関数に正しく渡されていないのではないかと思い始めたので、そこにコード行を追加して例外をスローし、それらが何であるかを示しました。以下を追加しました。

throw new ArgumentException("endLat", string.Format("endLat: {0}, endLong: {1}", endLat, endLong));

そして今、クエリを実行すると、次のエラーが表示されます。

マネージド ストアド プロシージャ GetDistance の実行が次のエラーで失敗しました: 呼び出しのターゲットによって例外がスローされました。endLat パラメータ名: endLat: 1033、endLong: 1033。

ここで問題は次のようになります: 実際の緯度の値を取得して、フィルター内のその関数を通過させるにはどうすればよいでしょうか? 現在、言語コードのみが渡されているようです。

4

3 に答える 3

2

[Zip].[Latitude] はメンバー式です。これを数値として関数に渡すために、SSAS は ([Zip].[Latitude], Measures.CurrentMember) に相当する値を返します。また、MDX では、あるディメンションを別のディメンションに基づいて直接フィルター処理することはできません。定義上、異なるディメンションは完全に独立しており、OLAP用語では、すべての製品がすべての Zip ロケーションに存在する可能性があります。

ロジックが次のように見える必要があると私が思うのは次のとおりです。

select   
NONEMPTY([DimProducts].[Product].[Product] *
FILTER([Zip].[Zip].[Zip] , ZipCalculatorLib.GetDistance(43.474208, [Zip].[Latitude].CurrentMember.MemberValue, 96.687689, [Zip].[Longitude].CurrentMember.MemberValue) < 100),[Measures].[RowCount])  on rows,        [Measures].[RowCount] on columns
from     MyCube;

これは、100 マイル以内の緯度/経度を持つすべての Zip メンバーを取得し、それを製品とクロス結合してから、空でない RowCount を持つメンバーを返します。

于 2009-10-28T00:55:48.360 に答える
1

私はサブキューブを使用して問題を解決することになりました。サブキューブを作成することで、距離をフィルタリングすることができました。その後、探していたディメンションを選択しました。これが私が最終的に得たものです...

create subcube MyCube as
select  Filter
        (
            (
                [DimLocation].[Latitude].[Latitude], 
                [DimLocation].[Longitude].[Longitude] 
            ), 
            (
                ZipCalculatorLib.GetDistance(
                    43.474208, 
                    [DimLocation].[Latitude].CurrentMember.MemberValue, 
                    96.687689, 
                    DimLocation.Longitude.CurrentMember.MemberValue) < 100
            )
        ) on 0 from MyCube;

select  DimProducts.Product.Product on rows,
        Measures.RowCount on columns
from       MyCube;
于 2009-11-03T20:00:43.540 に答える
1

これをマイルで計算していることをどのように確信していますか?

SQL Server 2008 が利用可能かどうかはわかりません。利用できる場合は、地理データ型を使用して距離を計算する必要があります。

そうでない場合は、SharpMap や Proj.Net などのライブラリを確認してください。これらのライブラリを使用すると、真の地理的ポイントを構築し、それらのオブジェクト間の正確な距離を計算できます。

于 2009-10-13T21:18:41.470 に答える