可供选择的聚合
2007-11-11 09:01:38 来源:WEB开发网当人们想起 OLAP 多维数据集的结构时,他们通常想到的是一组分层维度和一组使用求和来确定度量值的度量。多维数据集通常包括通过使用求和来聚合的度量。目前存在各种其他的聚合类型,但 Analysis Services 并非对所有这些类型都提供本机支持。非传统聚合的一个典型示例是库存分析。当您分析库存时,您不需要通过对三个月来的库存数字求和来确定每个季度的库存;您只需要使用该季度最后一个月的库存量。您可以在 Analysis Services 中轻松地实现这种聚合,但它不是您可以选择的本机聚合类型之一。我们先讨论本机类型,然后了解如何实现两个非本机聚合类型。
本机聚合
首先,我们先提供一些术语。多维数据集单元是多维数据集中的一个位置,各个维度在该位置相交。就像您可以在 X、Y 和 Z 轴上使用数值来标识三维空间中的点一样,您可以使用每个维度中的成员来标识多维数据集中的单元。因为每个维度都有一个默认的成员,所以您不必显式列出每个维度的成员,就可以唯一地标识一个多维数据集单元。例如,元组 (USA, Drinks) 足以标识 FoodMart 2000 Sales 多维数据集中的一个唯一单元(虽然 Sales 多维数据集有 12 个维度),因为其他 10 个维度位于其默认成员的位置上(也就是说,它们已经被占用,因此您无需对它们显式命名)。
每个多维数据集单元对于多维数据集的每个度量都有一个值。有些多维数据集单元的度量值是加载的(也就是说,直接来自源数据),而有些多维数据集单元的度量值则是由聚合来确定的。聚合是 Analysis Services 通过对其他多维数据集单元执行某些数学函数来确定的值。简言之,任何叶级单元的值都是加载值,这意味着这些值是基于源数据计算的,而不是基于其他单元中的值计算的。非叶级单元值是聚合确定的。叶级单元是完全由最低层的维度成员(没有子级的维度成员)标识的单元。
asp?url=/library/en-us/dnsqlmag03/html/AlternativeAggregationsTable_01.asp" target="_blank">表 1 显示了 Analysis Services 的本机聚合类型(数学函数)和它们的说明。非重复计数是一个特殊类型,这里应该解释一下。Analysis Services 只允许一个多维数据集中有一个非重复计数度量,而且非重复计数度量的值从不聚合(即从不通过其他单元值来确定)。在处理多维数据集时,Analysis Services 直接从事实数据表派生非重复计数度量值。非重复计数值是由特定多维数据集单元所标识的非重复类型的事实数据表记录数来确定的。例如,如果多维数据集单元是 (1997, Beverages),则非重复计数就是 1997 年期间在 Beverages 产品类别中出现的不同类型的事实数据表记录的数量。当您创建非重复计数度量时,应在事实数据表中指定一列,用于确定事实数据表记录的类型。非重复计数度量不同于典型的计数度量,因为非重复计数不是事实数据表记录的计数,而是事实数据表中特定列的非重复值的计数。数据库管理员通常使用非重复计数来确定当一个以上的事实数据表记录来自同一个事务时存在的唯一事务的数量。
本机聚合类型的一个特征是,Analysis Services 在所有多维数据集维度中用同样的方式来处理它们。非本机库存聚合则不具备这一特征。对库存量进行聚合时,您要对除 Time 维度之外的所有维度使用求和。您可以通过使用最后一个子级(也就是最近的值)对 Time 维度进行聚合。图 1显示了 Product 维度如何将各个库存总数聚合为一个总和,而 Time 维度则使用最后一个子级。
非本机聚合
因为 Analysis Services 不提供对最后一个子级聚合的本机支持,所以您不得不自己创建聚合支持。对于如何实现此目的,您可以有几种选择。您可以在 Time 维度中使用计算度量、计算单元或自定义汇总公式。我倾向于使用将性能影响限制在多维数据集的最小百分比的方法。例如,FoodMart Sales 多维数据集包含除库存量度量之外的其他度量,因此我建议挑选一种不向其他度量增加额外处理的方法。Analysis Services 会计算每个度量的自定义汇总公式,因此自定义汇总不是解决这一问题的适当选择。您可以使用计算单元或计算度量方法来分离聚合处理,这样它只会影响库存量度量。当您在计算单元和计算度量之间进行选择时,您需要考虑两个情况。注意,计算单元只能随企业版的 sql server(WINDOWS平台上强大的数据库平台) 提供。但计算度量在支持钻取的多维数据集中会出现问题,因为当您指定计算度量作为标识多维数据集的单元的元组(即成员列表)的一部分时,不能使用钻取操作。
为了进行库存分析,我建议使用计算度量,这只是因为大多数 OLAP 前端工具都提供了创建计算度量的功能。例如,当您在 FoodMart Sales 多维数据集中使用以下计算度量公式时,它返回 [Unit Sales],就好象它是库存量一样:
IIF( Time.CURRENTMEMBER.LEVEL.NAME <> "Month",Time.CURRENTMEMBER.LASTCHILD,(Time.CURRENTMEMBER, [Unit Sales]) )
这个递归公式确定当前 Time 成员的级别名称是否为 Time 维度中的最低级别,如果不是,则返回当前成员的最后一个子级。该公式的 LASTCHILD 部分使公式不断重新进行递归求值,直到级别的名称为 Month;然后,该公式返回当前 Month 的 Unit Sales 值。
有些多维数据集不包含每个叶级 Time 成员的加载值。在那些多维数据集中,您不能使用上面那样简单的公式来确定度量的最近的值。我在构建一个用于跟踪软件缺陷的多维数据集时就遇到过这样的情况。该多维数据集是用包含缺陷状态转变的事实数据表构建的。软件质量保证流程通过 state 来跟踪缺陷,这些状态的名称包括 found but not assigned to a developer、assigned to a developer、fixed but awaiting the next product build、fixed but not verified 或 closed。缺陷状态转换就是从一种状态向另一种状态转换时发生缺陷的情况。例如,每个条目都包含缺陷 ID、说明、发生变化的日期、原来的状态和新的状态。我使用的事实数据表包含 date that the defect changed 状态、origination 状态和 destination 状态。要在多维数据集中创建一个返回任何时期的缺陷状态的度量,必须包括一个回溯到最近的 date that the defect changed 状态的公式:
IIF( Time.CURRENTMEMBER.LEVEL.NAME <> "Month",Time.CURRENTMEMBER.LASTCHILD,TAIL( FILTER( [Time].[1997].[Q1].[1] : Time.CURRENTMEMBER,NOT ISEMPTY( [Unit Sales] ) ) *{ [Unit Sales] }, 1 ).ITEM(0) )
这个 MDX 表达式比前一个复杂得多。该表达式背后的原理与前一个表达式一样,但并不是只使用 (Time.CURRENTMEMBER, [Unit Sales]) 作为 IIF() 函数的最后一个参数,它可以标识最近的非空月份。首先,采用包括所有月份的一组月份,从第一个月 ( [Time].[1997].[Q1].[1] ) 到当前月份 - 冒号运算符 (:) 标识成员范围 - 并筛选出空月份。然后,该表达式使用星号运算符 (*) 将 Unit Sales 与这组非空月份进行交叉联接,使用 TAIL() 函数将这个集合减少到最后一项。ITEM(0) 运算符将 TAIL() 函数(一个集合)的结果转换为它的第一项。
在上面的两个 MDX 示例中,我使用了 FoodMart Sales 多维数据集中的 Unit Sales,这样就可以对 MDX 进行试验。在实际应用中,您应该用加载的度量替换 Unit Sales。因为您必须使用本机 Analysis Services 聚合类型之一来创建加载的度量,所以当您将该度量与非叶级 Time 维度成员一起使用时,该度量不会返回有效信息。由于可能返回无效数据,您需要将加载的度量的可见性设置为 false,这样一来,您的应用程序的最终用户所能看到和使用的就只有计算度量了。当您选择了度量后,您可以在 Analysis Manager 的多维数据集编辑器的“属性”窗格中更改加载的度量的可见性。
目前还存在许多其他聚合类型,有些聚合类型十分简单。例如,一个普通的 OLAP 应用程序要对企业收益表进行建模。在收益表的最高级别,您需要从收入中减去支出,以创建净收入。在此维度中的所有其他级别,您需要通过使用求和来聚合帐户类别。在这种情况下,自定义汇总函数可能是最合适的选择。
计算度量、计算单元和自定义汇总都是可以帮助您定制聚合公式的工具。如果您知道如何使用 Analysis Services 的高级功能,Analysis Services 就显得非常灵活。我希望通过通读这些示例和解释,能有助于您更有创造性地考虑如何创建您的 OLAP 多维数据集,这样多维数据集就可以用适合您尝试解决的问题的方式来聚合度量值了。
更多精彩
赞助商链接