页面树结构
转至元数据结尾
转至元数据起始

在玩转数据模型的过程中,你是不是也被这些小烦恼缠上啦:

计算列到底是个啥?计算度量又是什么神秘 “物种”?

计算列和计算度量之间,到底藏着什么不同的小秘密?

碰到具体问题时,该怎么挑计算列和计算度量呢?


首先,计算列、计算度量的存在,主要是辅助我们在创建模型时更好的进行二次计算,那先来说说为啥要二次计算?打个比方,数据源就像一个食材库,可有时候,里面缺了咱们做菜(分析数据)要用的食材,这时候就得自己动手加工一下,比如把数据 “切一切”(分割)、给字段类型 “换换装”(转换),或者求个平均值、找同期值啥的。

注意,这里有个关键的知识点要划重点啦!与报表层面进行二次计算不一样的是,模型定义是全局二次计算,也即我们在数据模型层面定义了一个计算逻辑,它就能在多个报表或多个组件复用。

 

下面就让我们一个个来揭开计算列、计算度量它们背后的神秘面纱吧!

  • 计算列是在5.15的版本中产品新增,直接将字段添加到原始查询中的字段,成为子查询像数据源表的一部分参与运算;
  • 计算度则是使用MDX语法定义的度量,基于已有的度量数据展开计算。

两者的含义、作用、创建方式对比详情见下表:

分类

计算列

计算度量

定义

在表中新增列,每行值由自定义公式生成

在多维数据集(OLAP)中通过 MDX 表达式定义,基于已有度量进行二次计算

计算顺序

基于表中现有字段列,逐行计算,先于汇总操作

基于已有的度量值,先汇总数据,再基于汇总结果计算

作用层级

表结构层面,新增列成为表的一部分,作用于数据表内每行数据

度量层面,基于现有度量进一步运算,属于跨维度聚合数据(如按时间、产品类别汇总后计算)

创建入口

数据模型右侧维度区 “+” 号 或 仪表盘报表开发界面的数据维度区 “+” 号

数据模型右侧度量区 “+” 号 或 仪表盘报表开发界面的数据维度区 “+” 号

创建方式

直接进入编辑界面,手动编写表达式(支持字段选择和函数拖拽)

两种方式:

1. 向导式(内置时间计算、数学运算等模板,支持拖拽字段快速创建);
2. 复杂方式(手动编写 MDX 函数,支持函数搜索和示例参考)

支持函数

使用数据库函数或平台内置函数(如数值、文本、日期处理函数)

除了内置函数(含时间计算、聚合函数、逻辑判断等),还支持调用 MDX 的函数,官方文档:https://mondrian.pentaho.com/documentation/mdx.php


由于两者创建方式和计算方式略有不同,最终操作步骤和对应得出的结果也会有所差异,详情如下:

(1)新建计算列,字段皆来自于表字段

  • 创建计算列入口:

                                  在数据模型右侧维度区右上方“+”号或仪表盘报表开发界面的数据维度区右上方“+”号入口都可以新建计算列使用,如图:

  • 新建计算列:在这个界面中,有表达式编辑框、字段选择栏以及选择函数使用栏,可以根据实际需求,利用这些功能进行相关定义:

  • 例如我们创建的销售额计算列就是拖拽对应表的字段进行计算即可,如图:

(2)新建计算度量

  • 创建计算度量入口:

                                     在数据模型右侧度量区右上方“+”号或仪表盘报表开发界面的数据维度区右上方“+”号入口都可以新建计算度量使用,如下图:

     

  • 新建计算度量:

          方式(1)向导方式:简单选择进行快速计算 : 实现同期、前期、累计值等,此页签界面主要是提供内置的数学运算、时间计算以及其他计算类型,也即可通过简单的拖拽操作快速创建所需的计算度量,如下图:

方式(2)函数方式:使用mdx函数来实现各种复杂场景下的高级计算,可看到右侧边栏很多内置函数,点击函数可看左下方的说明和示例;

  • 例如我们新建销售额计算度量就可以选择函数方式创建,如图:

(3)创建报表,拖拽计算列和计算度量对比结果:

  • 拖拽销售额计算列展示,可看到是按行输出销售额计算列结果:

查看系统监控——SQL/MDX监控,涉及的区域和销售额计算列都是从业务数据源通过SQL查询,并且销售额计算列是在原表直接处理,然后和其他表字段一并输出:

  • 拖拽销售额计算度量展示,可看到销售额计算度量是汇总聚合后的结果:

查看系统监控——SQL/MDX监控,涉及的区域是从业务数据源通过SQL查询,但是销售额计算度量是在对原表数据分类汇总处理后,再基于汇总结果也即对已有的度量进一步计算处理:


  • 若把销售额计算列右键复制转度量,再拖拽销售额计算列-对应的度量进行展示,可看到也是根据维度分类聚合计算后输出销售额计算列-度量的结果:

同样,查看系统监控——SQL/MDX监控,涉及的区域和销售额计算列都从业务数据源通过SQL查询,并且销售额计算列是在原表直接处理,但与维度区普通销售额计算列不同的是,销售额计算列-对应的度量会进行多一层sum的汇总计算,然后再和其他表字段一并输出:



学习计算列和计算度量两者含义、作用、创建方式和对应结算结果差异后,我们继续来看看两者的应用场景有何区别?

常用应用场景对比说明如下表:

说明

场景说明

相同之处

(1)均支持数值计算、逻辑判断、日期处理等基础功能;
(2)均可通过自定义公式或函数扩展数据处理能力;
(3)均支持对原始数据进行分类、逻辑判断等。

计算列-
常用场景

转换数据格式、转换数据类型、或取整:

把数值或者日期转换成字符串,使用TOSTR函数

将时间戳转换成日期格式,使用UNIXTIMETODATE函数

将字符串类型数据格式转换成日期格式,使用STRTODATE函数

对字段取整,使用TOINTEGER函数

求明细数据对应某个日期前X天/年/月/季或日期时间差值等的日期时间计算:

获取当年第一天,可以通过YEAR函数获取当前年,再用CONCAT函数进行拼接;

返回日期之间的天数差,使用DATEDIFF函数

对原始数据分类判断使用:

对原始数据分类使用IIF函数判断;

对数据表数据的值进行case when判断再应用,可以使用计算列构造出是否

计算度量-
常用场景

对度量做复杂计算,方差、中位数等:

求销售收入的期末值,Tail函数filter函数结合处理;

求销售额的年方差,使用VAR函数

查询各个产品类别销售额的中位数,使用Median函数

查询销售额的4次方根,使用Power函数

汇总计算:

计算近两个月的销售额,使用AGGREGATE函数ParallelPerodex函数结合处理;

指定维度进行汇总,使用Fixed函数

按多个维度进行过滤汇总,aggregate函数nonemptycrossjoin函数结合处理;

对汇总数据排名、比较、分类处理:

查询各个产品销售额的排名情况,使用rank函数

计算两个时间段的比值,使用AGGREGATE函数;

对汇总后数据做判断,对度量进行case when判断处理;


接下来,让我们继续走进不同场景的实际示例,就像玩解谜游戏一样,看看在什么情况下,计算列是最佳 “搭档”,而什么时候计算度量又能 “大显身手”。多研究几个实际案例,就像多积累了几个通关秘籍,帮你透彻理解如何选用计算列和计算度量,保准让你豁然开朗!

(1)场景描述:计算两数值字段相乘,需要计算前判断若字段为空则显示0

  • 揭晓答案:对原始字段值直接判断处理,选用计算列,使用IFNULL 函数,当值为null时转成0,如果为””空时也可以转成0 :

预览结果:

(2)场景描述:值判断是否为空,数据源中存储的数据有null,需要判断最终展示的结果数据 为 null时 显示为 0 

  • 揭晓答案:判断展示结果数据,那就是对度量判断处理,得选用计算度量二次计算判断,通过IIF函数、IsEmpty函数进行判断,如下图表达式的含义:如果[销售额]度量为空,则返回0,否则返回1。

预览结果:

 

(3)场景描述:把订单模型订单表中的“区域”、“省份”、“城市”、“地址”这几个字段拼接成一个收货地址

  • 揭晓答案:直接拼接表字段应该使用计算列哦,创建计算列,使用CONCAT函数进行拼接,可以使用无数个字段或者常量。

预览结果:

 

(4)场景描述:需把指定成员拼接成一个字符串,例如如何把销售额前3的3个城市名称拼接成一个字符串显示

  • 揭晓答案:与例子3)不一样的是,这个需求是需要判断度量汇总后的值,再拼接实际汇总对应结果值,此时应该选用计算度量,如下图:

预览结果:

(5)场景描述:有一个“订单日期”字段,把它作为筛选器,当前值是2024年7月11,现在要取这个日期的前30天

  • 揭晓答案:对表字段判断处理,应该选用计算列,通过DATEADD 函数实现:

 


预览结果:

(6)场景描述:返回日期之间的天数差,比如计算下单到发货用了多久

  • 揭晓答案:对明细行字段判断处理,应该选用计算列,通过DATEDIFF函数实现:

 

预览结果:


(7)场景描述:查询购买商品次数大于1的客户数有多少

  • 揭晓答案:需基于维度汇总后的度量进行二次计算分析,创建计算度量,使用count、Filter 函数实现:

预览结果:

(8)场景描述:如何计算某些成员的销量,例如计算“产品名称”下的白米的销量

揭晓答案:

【推荐】方案一:如果计算度量只有指定成员汇总,可以优先使用计算列,计算结果通过计算列处理好再复制转度量使用计算列转度量走SQL引擎优化查询性能较好

【不推荐】方案二:接通过计算度量向导——计算类型选择“按指定成员集聚合度量”并勾选“白米”作为成员集。

  • 新建计算列-复制转度量:


  • 新建计算度量:

预览结果:

  • 查看系统监控-SQL/MDX记录,可看到计算列转度量的查询耗时比直接计算度量处理快很多:

 

(9)场景描述:如何排除某些成员的指标,例如排除产品类别为点心的销售额?

  • 揭晓答案:涉及成员的可以新建计算度量,通过AGGRGATE、EXCEPT函数处理:

注意:选维度成员下面的【产品类别】,上面维度那个包含了一个all成员,数据会翻倍;

预览结果:

(10)场景描述:按多个维度指定成员进行过滤汇总,例如计算2020年、东北区域、点心类别的销售额

  • 揭晓答案:涉及维度指定成员汇总处理,选用计算度量,通过AGGREGATE、NONEMPTYCROSSJOIN 函数实现;  

注意:如果要更多个维度,可以再嵌套一个NONEMPTYCROSSJOIN,用多了NONEMPTYCROSSJOIN 可能会存在性能问题。

预览结果:

 

(11)场景描述:指定维度进行汇总,例如需查询【区域】和【类别】的销售额合计值,但是又想显示区域的销售额与它进行对比

  • 揭晓答案:涉及维度汇总处理,选用计算度量,通过FIXED函数实现;  

预览结果:

 

(12)场景描述:报表查询涉及时间层次,勾选字段最小粒度到年月日,但是希望或者月份层次的度量前期值,如何处理?

  • 揭晓答案:涉及时间层次汇总处理,选用计算度量,通过计算度量知道日期的CurrentMember.parent.PREVMEMBER值实现;  

预览结果:

 

(13)场景描述:仪表盘进度图组件需要获取度量数据里的最大值作为目标值, 例如降序的话第一个一直的100%的效果,如何处理

  • 揭晓答案:可以新建计算度量,通过MAX函数获取到最大值,然后把目标值设置为这个最大值使用

注意:像示例(9)选维度成员下面的【发货区域】,上面维度那个包含了一个all成员,数据会翻倍;

预览结果:

(14)场景描述:动态获取往月的月末值和当前月前一天值, 例如根据月份筛选器判断,往期拿当月最后一天的值,本月拿前一天的值,如何处理

  • 揭晓答案:可以新建计算度量,结合模型参数值判断

image-2024-10-25-14-35-39-717.png

预览结果:

(15)场景描述:希望计算去除某个维度影响的标准差值, 例如排除发货区域这个维度影响,计算产品类别对应的销售额标准差值,如何处理?

  • 揭晓答案:可以新建计算度量,使用STDEV和EXCLUDE函数判断处理

预览结果:

(16)场景描述:计算对应所选时间对应的去年年末度量值, 例如根据维度年月判断,获取去年年末的值作为业务的年初结果使用,如何处理

  • 揭晓答案:可以新建计算度量,获取所选维度对应的CurrentMember.PARENT.PREVMEMBER.lastchild【找到当前成员-再找其父成员-接着找父成员同级的前一个成员-最后获取这个成员的最后一个子成员】值判断获取

预览结果:

(17)场景描述:计算多维度的度量百分比排名, 例如发货机构华北里面有8个产品类别分组,希望计算点心产品组内数量排名第三,就是(8+1-3)/8*100&=75%,如何处理

  • 揭晓答案:可以新建计算度量,其中分子就是维度层次按指定度量排序后再计算其排名生成的

预览结果:

此示例比较复杂,附上资源:百分比排名测试资源.xml


优先选择计算列或计算度量的场景决策树:

1、是否需要聚合?

是 → 计算度量(如场景2、4、7、8、9、10、11)

否 → 计算列(如场景1、3、5、6)

2、是否需要动态上下文?

是 → 计算度量(如结果依赖维度和度量聚合后的数据)

否 → 计算列(如结果仅依赖原始数据)

3、是否涉及成员筛选?

是 → 计算度量(如场景8、9、10)

否 → 根据其他条件判断。

典型错误规避:

  • 误用计算列处理聚合:
  • 计算列无法感知维度上下文,无法正确计算动态汇总值(如最大日期对应的金额汇总值);
  • 误用计算度量处理明细数据:
  • 计算度量需依赖聚合逻辑,无法直接处理行级字段拼接(如地址拼接)。


在本篇文章中,我们继续结合具体案例演示了计算列和计算度量两者在计算逻辑方面的特性,相信我们遇到不同业务场景需求时,都会快速定位应选用计算列还是计算度量,确保业务展示结果正确性啦!

当你掌握了这些核心技能,就能像数据魔法师一样灵活驾驭数据模型。那么最后一个问题来了 —— 如何正确使用数据模型参数?别急,这正是我们下篇要解锁的终极秘籍!