2009-10-13 160 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