带你了解 DAX 筛选转换原理


各位读者周五好~
每天获得一个新的技巧,在无数个小而确定的改变之后,你的积累将在意想不到的时间和地点开花结果。今天小编给大家带来的是DAX筛选转换原理,希望在阅读之后可以对你有所帮助。

今天通过几个小案例理解一下DAX的筛选转换,一起来看看吧。
有两张表:
表一:公司ID

file

表二:车型ID

file

表一和表二通过公司ID进行关联。

需求一:在表一里把表二中属于表一对应公司的ID最大的车型找出来。

思路:添加计算列,找到对应公司里的最大ID,对应的车型也就找到了。
方法:

最大ID车型 =
VAR ID_max =
    MAXX ( RELATEDTABLE ( '车型ID' ), '车型ID'[ID] )
VAR MAX_ID =
    MAXX ( FILTER ( '车型ID', '公司ID'[公司ID] = '车型ID'[公司ID] ), '车型ID'[ID] )
RETURN
    CALCULATE ( VALUES ( '车型ID'[车型] ), '车型ID'[ID] = MAX_ID )

file

度量值里提供了两种查找最大ID的方法。

VAR ID_max是通过表的物理关系进行查找,VAR MAX_ID是通过filter筛选进行查找。

在计算列里写表达式会产生行筛选,即按公司进行筛选,每行的公司会筛选出本公司下面的那些车型ID,MAXX会筛选出最大的车型ID,度量本身会有隐式的calculate,即会把行筛选转换为列表筛选,从而每行的公司对应的最大车型ID是本公司的。

需求二:在表一里添加每个公司对应车型销售额的合计。

表二有各公司车型的销售额明细,需要聚合后添加到对应公司里。

试验一:

尝试用SUMX把表二里各车型销售额聚合,然后再写到表一里。

 销售额 =
SUMX ( '车型ID', SUM ( '车型ID'[销售额] ) )

file

结果是4500,而且都是4500,为何是这样的结果呢?
我们看表二会发现,所有车型销售额合计是500,结果是4500?这个结果是怎么得来的,DAX内部引擎进行了怎样的计算呢?这里需要理解SUMX和SUM的计算原理。

SUM给我们的感觉就是加总,就是聚合求和,其实SUM进行的是SUMX的运算。SUM ( '车型ID'[销售额] )是通过SUMX迭代了表二的所有行,然后聚合汇总销售额得到500。

然后就是SUMX ( '车型ID', 500),SUMX迭代表二的每行,然后聚合每行的500,表二一共有9行,聚合之后就是500*9=4500,结果就是这么计算出来的。
这个公式聚合了所有值,没有进行筛选转换,那怎么进行筛选转换呢?答案是加CALCULATE。加了就可以转换了吗?

试验二:

 销售额 =
CALCULATE(SUMX ( '车型ID', SUM ( '车型ID'[销售额] ) ))

file

怀着激动的心情,加完CALCULATE回车. . . .是转换了,但是结果也不对,不知道这些数字又是怎么计算出来的?DAX是怎么进行转换计算的呢?
要理解这一点,还要介绍一个知识点,就是DAX的扩展表概念,就是表关联。
当添加CALCULATE把行筛选转换为列表筛选后,对应值发生了变化,说明的确是进行了筛选转换。但是转换的有问题,这里我们要清楚是哪些值进行了筛选转换。

筛选转换就是把表中一每个公司对应的车型的销售额进行聚合汇总,即由原来的所有公司筛选转换为对应公司的销售额。转换的是对应公司的销售额,那公式里'车型ID'[销售额]就会发生相应的改变。

根据刚才的介绍,SUM('车型ID'[销售额])=SUMX(表二,'车型ID'[销售额]),奔驰所在的行进行筛选转换后,这里的SUM ( '车型ID'[销售额] )迭代的就是奔驰所在的那些行的销售额了,因为表一和表二是关联的,刚才提到了扩展表的概念,说的就是这个意思。

通过表二我们得知奔驰的销售额是135。CALCULATE(SUMX ('车型ID', SUM ( '车型ID'[销售额] ) ))= CALCULATE(SUMX ( '车型ID', 135)),迭代表二的每行,因为筛选转换,只迭代奔驰的那些行,一共3行,那迭代聚合后就是135*3=405,和DAX运行结果一样。

其它的公司一样的道理,通过筛选转换和扩展表原理计算得出了这样的结果。那我们想要正确的结果,应该怎么调整呢?

试验三:

刚才提到SUM ( '车型ID'[销售额] )=SUMX(表二,'车型ID'[销售额]),它本身如果不加CALCULATE直接写入公式中的话,是没有进行列表筛选转换的。
SUMX本身的迭代器函数,会对参数一的表进行逐行迭代,加上CALCULATE就会把行筛选转换为列表筛选。刚才没有得到正确的结果就是因为SUMX在迭代的时候行筛选没有转换为列表筛选造成的。我们加上CALCULATE看下结果吧。

 销售额 =
CALCULATE ( SUMX ( '车型ID', CALCULATE ( SUM ( '车型ID'[销售额] ) ) ) )

file

和表二的明细数据比对后,发现结果正确,终于写对了!!!
总结一下刚才的尝试过程,得出结论,要想得出正确的结果需要把行筛选转换为列表筛选,并且用到了扩展表的原理。
如果把SUM ( '车型ID'[销售额] )单独写一个度量值,再放回公式里会怎样呢?

 SalesAmount =
CALCULATE ( SUMX ( '车型ID', [SalesAmount] ) )

file

结果是一样的,这两种方式有什么区别呢?

SUM ( '车型ID'[销售额] )vs. [SalesAmount]

虽然[SalesAmount]= SUM ( '车型ID'[销售额] )。但是,[SalesAmount]作为一个度量是有隐式calculate的。即:

[SalesAmount]=CALCULATE([SalesAmount])

而单独在公式里写SUM ( '车型ID'[销售额] )是没有隐式calculate的,没有CALCULATE就没有列表筛选转换,就得不到正确的度量。刚才的公式是不是感觉太繁琐呢?有没有简单的公式可以一步到位的呢?
答案是:当然有了,来看下优雅的解决方式:

 优雅的度量 =
[SalesAmount]

file

就一个度量值就搞定了,简洁,正确,优雅,为何能这么简单呢?
回顾刚才的一系列尝试过程,我们都在谈两个问题,一个是筛选转换,即行筛选转换为列表筛选,一个是扩展表的概念。
表一和表二有关联,并且[SalesAmount]度量含有隐式的calculate支持筛选转换,当表一奔驰所在行进行行筛选时通过表关联扩展到表二的对应车型,通过calculate把行筛选转换为列表筛选就得到了正确的结果。
以上就是我理解的DAX的筛选转换原理。

小伙伴们有什么意见可以留言交流。
欢迎批评指正哦~~

file

  • PowerPivot工坊原创文章,转载请注明出处!

Power Pivot工坊