之前提到过,数据模型是DAX的灵魂,所有DAX表达式的计算都离不开数据模型。这里的数据模型其实指的就是表与表之间的关系,所有的模型关系组成了数据模型,当模型关系改变时,即使DAX表达式一致,那计算出来的结果也有可能会不一致。
由于模型关系非常重要,牵一发而动全身,改变关系时会影响到所有度量值的计算。但在某些场景下,某个比较特殊的度量值指标又必须更改模型关系后才可以计算出来,那么这时候就可以只在这个特殊度量值中使用CROSSFILTER函数以及USERELATIONSHIP函数来临时改变模型关系,使得影响范围只存在于这个特殊度量值中,既能达成目的,又不会修改实际的模型关系,从而不会影响到其它度量值的计算。
本篇文章介绍的就是CROSSFILTER函数的使用与注意事项。
CROSSFILTER函数的语法结构与作用
语法:
CROSSFILTER(<columnName1>, <columnName2>, <direction>)
CROSSFILTER函数的前两个参数代表一条模型关系在两端的连接字段,只能使用基础列,而且必须使用完全限定性的写法。<columnName1>
通常表示位于多端的连接字段,<columnName2>
则表示位于一端的连接字段,但即使颠倒了顺序也无妨,该函数会自动调整成正确的顺序,因为CROSSFILTER函数针对的是现有的关系,所以能够清楚的知道连接字段分别来自哪一端。
CROSSFILTER函数的最后一个参数代表关系的筛选器传递方向,即关系箭头的指向,是一个枚举类型的参数,有以下几个选项:
-
NONE:无交叉筛选,即断开关系
-
BOTH:双向筛选
-
ONEWAY:单向筛选,只能用在一对多或多对一关系中
-
OneWay_LeftFiltersRight:
<columnName1>
一方的筛选器会筛选<columnName2>
一方,只能用在多对多关系中 -
OneWay_RightFiltersLeft:
<columnName2>
一方的筛选器会筛选<columnName1>
一方,只能用在多对多关系中
作用:
CROSSFILTER函数属于筛选调节器,可以在CALCULATE函数的计算过程中临时修改现有的模型关系的筛选器传递方向,即关系箭头的指向,甚至可以临时断开该关系的连接,效果持续至其所在的CALCULATE函数计算完成。需要注意,该函数修改的是现有的模型关系,因此前两个参数指定的连接字段若不能指代一个存在的关系,或者指定的连接字段属于不同的关系,则会报错。
简单来说就是只能更改已经存在的关系的关系箭头指向,甚至断开该关系也可以,但不能给两个原本没有关系的表建立关系。
CROSSFILTER函数的应用
下面通过一些案例来帮助理解CROSSFILTER函数的用法。
先来看第一个例子,如下图所示,矩阵中的行标签来自产品表,而产品表与订单表为一对多关系,现在想要计算各产品的总销量,一般可以使用ALL函数移除掉矩阵行标签提供的产品名称筛选器,从而使所有数据都可见,进而汇总得到总销量。
以上计算总销量时的场景也可以使用CROSSFILTER函数来实现,如下图所示:
在该案例中,CROSSFILTER函数的第三参数被设置成NONE,表示断开关系,即产品表与订单表之间的关系被临时断开。而矩阵的行标签来自产品表,由于关系被断开,该产品表上的筛选器无法传递给订单表,使得订单表的数据全部可见,最终汇总得到总销量。
虽然使用ALL函数与CROSSFILTER函数都可以得到正确的结果,但其中的计值流程是不一致的,ALL函数方案是移除筛选器,从而使所有数据可见,进而汇总得到总销量。而CROSSFILTER函数则是断开了关系,使得产品表的筛选器无法传递给订单表,属于掀桌子的玩法。这里只是为了演示CROSSFILTER函数的作用,如果实际应用,还是更推荐ALL函数的方案。
再来看下面这个案例。如下图所示,现在想要计算各个城市中售出过的产品类别个数,以进行产品覆盖分析。首先,矩阵行标签来自订单表中的客户城市字段,而要统计的产品类别信息却存储在产品表中,因此难点在于订单表逆向筛选产品表,那么这个可以使用之前介绍过的基于扩展表原理的逆向筛选的套路来解决,即下图所示的方案。
但掌握了CROSSFILTER函数后,可以直接修改模型关系,使产品表与订单表之间的关系箭头变成双向的,这样也可以达到目的,如下图所示:
另外,在这个案例中,通过CROSSFILTER函数临时修改模型关系的性能比扩展表方案的性能要更快,因此更推荐CROSSFILTER函数的方案。
总结
出于性能考虑,一般不建议在模型中将关系的筛选方向设置为双向,这会减慢报表的运行速度,而且有可能会影响到其它度量值的计算。因此在有需要时,可以在公式中使用CROSSFILTER函数来临时更改模型关系,这既不会影响到其它度量值,而且也兼顾了性能。
另外需要注意,CROSSFILTER函数是筛选调节器,其效果持续至其所在的CALCULATE函数计算完成,并且它只修改现有模型关系的筛选器传递方向,不会影响计值环境里的任何筛选器,但由于关系箭头的指向被更改,这些筛选器能筛选的范围可能也会因此改变,但筛选的值并不会变。