使用Mondrian / MDX按宿舍分组:总和和行数与平均行为

时间:2015-04-11 13:29:15

标签: mdx pentaho olap mondrian

我试图在一组季度中聚合(总和和平均值),但取决于我使用的方法,我得到的结果不同。我想了解原因。

以下基本查询说明了我的数据(Pentaho SteelWheels样本):

SELECT  {Measures.Sales, Measures.Quantity} ON COLUMNS
,       ORDER(
          Time.Quarters.Members,
          Time.CurrentMember.Caption,
          BASC
        ) ON ROWS
FROM    SteelWheelsSales

结果:

Time |  Sales     |Quantity
-----+------------+---------
QTR1 |  445094.69 |  4561
QTR1 |  877418.97 |  8694
QTR1 | 1111260.1  | 10995
QTR2 |  564842.02 |  5695
QTR2 |  847713.97 |  8443
QTR2 |  869565.24 |  8480
QTR3 |  687268.87 |  6629
QTR3 | 1145308.08 | 11311
QTR4 | 1980178.42 | 19554
QTR4 | 2117298.82 | 20969

因此行标题是季度的标题,QTR1,QTR2,QTR3和QTR4的不同出现都属于特定年份(所以第一个QTR1实际上是[2003]。[QTR1],第二个是[2004] ]。[QTR1]和第3个是[2005]。[QTR1],依此类推)

我想要的是将[QTR1]的所有出现都视为单个组的结果,以及单元格值汇总销售数量度量的结果。让我们说我想看到至少总和(不论年数的所有季度1,2,3和4的总量)和平均值(所有季度1,2,3和4的平均数量,不管年)

现在,我看到了这个问题:

How can I merge two members into one in a query?

虽然该解决方案确实有帮助,但它要求我列举我需要组合在一起的季度。我想动态地这样做。

我提出了这个问题:

WITH
SET     OrderedQuarters
AS      Order(
          Time.Quarters.Members,
          Time.CurrentMember.Caption,
          BASC
        )
SET     UniqueQuarters
AS      Filter(
          OrderedQuarters,
          OrderedQuarters.Item(
            OrderedQuarters.CurrentOrdinal-1
          ).Caption <> Time.CurrentMember.Caption
        )
MEMBER  Measures.QuantitySum
AS      Sum(
          Filter(
            OrderedQuarters,
            UniqueQuarters.Item(
              UniqueQuarters.CurrentOrdinal
            ).Caption = Time.CurrentMember.Caption
          )
        , Measures.Quantity
        )
MEMBER  Measures.Counter
AS      Count(
          Filter(
            OrderedQuarters,
            UniqueQuarters.Item(
              UniqueQuarters.CurrentOrdinal
            ).Caption = Time.CurrentMember.Caption
          )
        )
MEMBER  Measures.[Sum over Count]
AS      Measures.QuantitySum / Measures.Counter
MEMBER  Measures.AvgQuantity
AS      Avg(
          Filter(
            OrderedQuarters,
            UniqueQuarters.Item(
              UniqueQuarters.CurrentOrdinal
            ).Caption = Time.CurrentMember.Caption
          )
        , Measures.Quantity
        )
SELECT {Measures.QuantitySum
       ,Measures.Counter
       ,Measures.[Sum over Count]
       ,Measures.AvgQuantity} ON COLUMNS
,       UniqueQuarters        ON ROWS
FROM    SteelWheelsSales

这给出了这个结果:

Time | QuantitySum | Counter |  Sum over Count  | AvgQuantity
-----+-------------+---------+------------------+----------------
QTR1 |       24250 |       3 |  8083 3333333333 | 8083.3333333333
QTR2 |       22618 |       3 |  7539.3333333333 | 8083.3333333333
QTR3 |       17940 |       2 |  8970            | 8083.3333333333
QTR4 |       40523 |       2 | 20261.5          | 8083.3333333333

现在,虽然[QuantitySum]和[Sum over Count]指标给出了我想要的结果,但我并不完全满意:

  1. 使用Sum显式计算[QuantitySum]。我希望隐式计算它,因为它已经在多维数据集中定义为总和聚合度量
  2. 我明确地计算了[Sum over Count]计算量度的平均值。我想使用Avg()并尝试使用Measures.AvgQuantity,但这似乎并不像我期望的那样。看起来它计算了Q1的平均值,然后它也重复了其他季度的值。为什么? Sum和Count似乎完全按预期工作,为什么Avg如此不同?

2 个答案:

答案 0 :(得分:1)

就微软的AdvWrks立方体而言,Date维度的结构略有不同,因此很容易实现Qrt1 / Qtr2 ..的聚合。

以下是包含的层次结构的整体集合:

enter image description here

以下是连接到季度的两个层次结构:

enter image description here

Date.Calendar用户层次结构的级别包括member_caption中的年份:

enter image description here

而属性层次结构Date.Calendar Quarter of Year的字幕与脚本中的字幕类似:

enter image description here

WITH 
  SET OrderedQuarters AS 
    Order
    (
      [Date].[Calendar Quarter of Year].[Calendar Quarter of Year].MEMBERS
     ,[Date].[Calendar Quarter of Year].CurrentMember.Member_Caption
     ,BASC
    ) 
  MEMBER Measures.AvgOrderCount AS 
    Avg
    (
      (EXISTING 
        [Date].[Calendar Year].[Calendar Year].MEMBERS)
     ,[Measures].[Order Count]
    ) 
SELECT 
  {
    [Measures].[Order Count]
   ,[Measures].[AvgOrderCount]
  } ON COLUMNS
 ,OrderedQuarters ON ROWS
FROM [Adventure Works];

返回以下内容:

enter image description here

EXISTING函数的替代方法是与季度层次结构的当前成员交叉连接。这给出了相同的结果:

WITH 
  SET OrderedQuarters AS 
    Order
    (
      [Date].[Calendar Quarter of Year].[Calendar Quarter of Year].MEMBERS
     ,[Date].[Calendar Quarter of Year].CurrentMember.Member_Caption
     ,BASC
    ) 
  MEMBER Measures.AvgOrderCount AS 
    Avg
    (
      ([Date].[Calendar Quarter of Year].CurrentMember*  //EXISTING 
        [Date].[Calendar Year].[Calendar Year].MEMBERS)
     ,[Measures].[Order Count]
    ) 
SELECT 
  {
    [Measures].[Order Count]
   ,[Measures].[AvgOrderCount]
  } ON COLUMNS
 ,OrderedQuarters ON ROWS
FROM [Adventure Works];

因此,如果在蒙德里安没有existing,那么请参考Ethen的答案,那么这可能会强制计算背景:

MEMBER  Measures.AvgQuantity
AS      Avg(
          (Time.Years.Members * Time.CurrentMember)
        , Measures.Quantity
        )

基于上面的内容,我想知道你是否可以将过滤后的集合加入多年:

MEMBER  Measures.AvgQuantity
AS      Avg(
          Filter(
            OrderedQuarters,
            UniqueQuarters.Item(
              UniqueQuarters.CurrentOrdinal
            ).Caption = Time.CurrentMember.Caption
          )
         * Time.Years.Members
        , Measures.Quantity
        )

答案 1 :(得分:1)

这本身并不是一个答案,因为我还没有尝试过,而且我的MDX知识太老了,完全没有信心它会起作用。但是,正如在Twitter上提到的,我想知道以下是否会起作用?具体来说,使用Time.Years.Members作为要平均的成员列表。

WITH
SET     OrderedQuarters
AS      Order(
          Time.Quarters.Members,
          Time.CurrentMember.Caption,
          BASC
        )
SET     UniqueQuarters
AS      Filter(
          OrderedQuarters,
          OrderedQuarters.Item(
            OrderedQuarters.CurrentOrdinal-1
          ).Caption <> Time.CurrentMember.Caption
        )
MEMBER  Measures.QuantitySum
AS      Sum(
          Filter(
            OrderedQuarters,
            UniqueQuarters.Item(
              UniqueQuarters.CurrentOrdinal
            ).Caption = Time.CurrentMember.Caption
          )
        , Measures.Quantity
        )
MEMBER  Measures.Counter
AS      Count(
          Filter(
            OrderedQuarters,
            UniqueQuarters.Item(
              UniqueQuarters.CurrentOrdinal
            ).Caption = Time.CurrentMember.Caption
          )
        )
MEMBER  Measures.[Sum over Count]
AS      Measures.QuantitySum / Measures.Counter
MEMBER  Measures.AvgQuantity
AS      Avg(
          Time.Years.Members
        , Measures.Quantity
        )
SELECT {Measures.QuantitySum
       ,Measures.Counter
       ,Measures.[Sum over Count]
       ,Measures.AvgQuantity} ON COLUMNS
,       UniqueQuarters        ON ROWS
FROM    SteelWheelsSales