MDX非层级属性下实现跨年度月度连续累计的方法
问题错误根因
原代码的核心问题是把无层级关联的两个独立维度属性(Calendar Year、Month of Year)做笛卡尔积范围计算,完全脱离了真实时间轴的先后顺序:
- 两个独立属性没有内建的绑定关系,计算出来的范围不是“时间上从起点到当前选中年月的连续月份”,而是“所有年份值≤当前选中年、月份序号值≤当前选中月”的所有属性交叉组合
- 这就导致两个典型偏差:
- 累计范围和时间先后完全错位:比如计算2012年1月的累计时,实际聚合的是所有年份≤2012、月份序号≤1的组合(即2011年1月、2012年1月),跳过了2010年12月、2011年2-12月的所有周期值,最终得到396的错误结果
- 不存在自然年度重置的逻辑基础,之所以看起来像是新一年重置累计,本质是月属性的范围被截断到了小于等于当前月,根本没有覆盖到之前年度的高月份值
正确实现思路
因为两个独立属性本身没有时间先后的绑定关系,必须借助Date维度下最细粒度的、天然按时间顺序排序的日属性([Date].[Date])作为时间锚点,不能直接在独立属性上做范围计算:
- 先通过
NonEmpty定位当前行上下文(当前选中年、当前选中月)对应的最细粒度日期的时间边界 - 取从维度最早日期,到这个时间边界之间的所有连续日期成员,对原始订单量做聚合,就是从全周期起点开始的连续累计值
可直接运行的适配代码
完全保留原查询的维度筛选逻辑,适配Excel单独拖拽年、月独立属性的使用习惯,不需要依赖完整的Calendar层级:
WITH // 全周期连续月度累计度量值 MEMBER [Measures].[CUM. MONTH - 全周期累计] AS AGGREGATE( // 定位当前选中年月对应的周期结束日期 Tail( NonEmpty( [Date].[Date].[Date].ALLMEMBERS, ( [Date].[Calendar Year].CurrentMember, [Date].[Month of Year].CurrentMember, [Measures].[Internet Order Quantity] ) ) ).Item(0) AS [CurrentPeriodEnd], // 取最早日期到当前周期结束日的所有连续日期做聚合 null:[CurrentPeriodEnd], [Measures].[Internet Order Quantity] ) // 查询逻辑和原写法完全一致,无任何额外层级依赖 SELECT NON EMPTY { [Measures].[Internet Order Quantity], [Measures].[CUM. MONTH - 全周期累计] } ON COLUMNS , NON EMPTY { ( [Date].[Calendar Year].[Calendar Year].ALLMEMBERS * [Date].[Month of Year].[Month of Year].ALLMEMBERS )} DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS FROM [Adventure Works] CELL PROPERTIES VALUE, BACK_COLOR, FORE_COLOR, FORMATTED_VALUE, FORMAT_STRING, FONT_NAME, FONT_SIZE, FONT_FLAGS
运行结果匹配说明
修改后的计算结果完全和预期一致:
- CY2010 December:Qty=14,累计值=14
- CY2011 January:Qty=144,累计值=14+144=158
- CY2011 February:Qty=144,累计值=158+144=302
- CY2011 December:累计值=2230
- CY2012 January:Qty=252,累计值=2230+252=2482
- CY2012 February:Qty=260,累计值=2482+260=2734
注:该度量值支持用户在Excel中单独拖拽年、单独拖拽月、年和月组合拖拽的所有场景,不会出现累计错位、年度重置的问题。
内容的提问来源于stack exchange,提问作者Wilhuff Tarkin
相关产品推荐
相关产品推荐

