2009-10-13 141 views
1

我正在使用SQL Server 2005 Analysis Services,我試圖計算一個MDX查詢內的距離 - 這樣我就可以計算出當前位置附近的物品的數量。我創建了一個緯度爲&經度的維度,並且還創建了一個.NET程序集來完成數學運算 - 但我很難在查詢中解決這一切。MDX地理距離計算

我的查詢找到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)); 

,現在當我跑我的查詢,我得到以下錯誤:

Execution of the managed stored procedure GetDistance failed with the following error: Exception has been thrown by the target of an invocation.endLat Parameter name: endLat: 1033, endLong: 1033.

所以,現在的問題就變成了:我怎麼得到我的實際緯度值通過在過濾器中的功能?看起來只是一個語言代碼正在被傳入。

回答

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; 
1

你怎麼確定你是以英里計算的?

我不確定SQL Server 2008是否可用,如果是,則應使用其地理數據類型來計算距離。

如果不是,請檢查SharpMap和Proj.Net等庫 - 它們可以讓您建立一個真正的地理點並計算這些對象之間的準確距離。

+0

.net代碼中的計算是以英里爲單位的近似距離。這不是確切的,但足夠接近 - 因爲我不是指導導彈,只是尋找庫存:) SQL 2008不適用於這個項目。 – 2009-10-13 21:25:23

2

[郵編] [緯度]是成員表達。爲了將此函數作爲數值傳遞給函數,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英里內,跨加入郵編成員與產品,然後返回具有非空RowCount的那些。

+0

Darren - 這看起來像是朝着正確的方向發展,但是所有發送給我的GetDistance函數的是Latitude和Longitude屬性的DefaultMember。任何想法爲什麼實際值不被傳遞? – 2009-10-29 19:33:53

+0

這可能意味着您的經度和緯度屬性與您的Zip屬性無關。我認爲Zip是你的關鍵屬性。你可能有另一個屬性是鍵,如果是這樣,你可以嘗試在過濾器表達式的第一部分使用它。 – 2009-11-30 00:49:36