MDX地理距离计算

发布于 2024-08-08 03:36:41 字数 1421 浏览 3 评论 0原文

我正在使用 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 失败,原因是 以下错误:异常已 由目标投掷 incalling.endLat 参数名称: 结束纬度:1033,结束长度:1033。

所以现在的问题变成:如何让实际纬度值通过过滤器中的该函数?看起来现在只是传递了一个语言代码。

I'm using SQL Server 2005 Analysis Services and I'm trying to calculate distance inside of an MDX query - so that I can get counts of the items that are near my current location. I've created a dimension with Latitude & Longitude, and have also created a .NET assembly to do the math - but am having a hard time getting it all to work out in the query.

My query to find items in a 100 mile radius looks something like this:

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

And my distance code in .NET looks like this:

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));
}

However, when I run that query, I come up with zero records. If I change the distance from 100 to 10000 - I get counts similar to what should be in the 100 mile radius. It looks like the .NET class isn't doing the square root - but I've tested that code many times over, and it looks right.

Does anyone have any suggestions as to where I should look to fix my problem?

EDIT:
I started to wonder if maybe the latitude and longitude weren't being passed into my GetDistance function correctly - so I added a line of code there to throw an exception to show me what they were. I added the following:

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

And now when I run my query, I get the following error:

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.

So now the question becomes: how do I get my actual latitudes values to pass through that function in the filter? It looks like just a language code is being passed in now.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

埖埖迣鎅 2024-08-15 03:36:41

[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 的成员。

[Zip].[Latitude] is a member expression. In order to pass this to a function as a numeric value SSAS will return the equivalent of ([Zip].[Latitude], Measures.CurrentMember). And you can't directly filter one dimension based on another in MDX. By definition, different dimensions are completely independent and in OLAP terms every product could potentially exist at every Zip location.

What I suspect that the logic would have to look like is the following:

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;

This gets all of the Zip members that have a latitude/longitude within 100 miles, cross joins that with products and then returns those that have a nonempty RowCount.

北方的巷 2024-08-15 03:36:41

你如何确定你是以英里为单位计算的?

我不确定 SQL Server 2008 是否可用,如果可用,您应该使用其地理数据类型来计算距离。

如果没有,请检查 SharpMap 和 Proj.Net 等库 - 它们可以让您构建真实的地理点并计算这些对象之间的准确距离。

How are you sure that you are calculating this in miles?

I'm not sure if SQL Server 2008 is availuable, if it is, you should use its geography datatype to calculate distances.

If not, check libraries like SharpMap and Proj.Net - They will let you build a true geographic point and calculate accurate distances between those objects.

陌上青苔 2024-08-15 03:36:41

我最终使用子立方体解决了我的问题。通过创建子立方体,我能够过滤距离 - 然后只选择我正在寻找的维度。这就是我最终得到的结果......

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;

I ended up solving my problem using a subcube. by creating the subcube, I was able to filter for the distance - and then after that just did a select for the dimension that I was looking for. Here's what I ended up with...

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文