首先,请死记:筛选和迭代是数据分析过程中的两大重要特性。
这也是 DAX 中,筛选上下文和行上下文的设计学来由。本文会非常简单地让您搞清楚迭代的概念。
开始。
很多从事业务的小伙伴问:到底什么是迭代?
精确地讲,迭代,是对一个集合中元素的遍历。
如下所示:
对于一个表的迭代,由于表是行的集合,每一行都表示同类事物的不同个体,如:不同的每一笔订单。很自然地可以将对表的迭代理解为对表中的行集合的迭代。
我们可以脑补一个箭头(例如:上图的右侧),这个箭头用来对表的行集合进行遍历,值得注意的是,我们不用关心它是怎么做到遍历的,不重要,只要知道表被遍历了。
在遍历的时候一般顺便可以做点坏事,例如,记住遍历过的每个值,这样就有了:
SUM.Value = SUM( SomeTable[Value] )
\\ 本质上等价于:SUM.Value =
SUMX( SomeTable , SomeTable[Value] )
SUMX 的含义是:
如果你没什么感觉就对了。因为 SUMX 在这个例子中根本没干什么坏事。
SUMX 可以做很多坏事,例如:
Order.Sales =
SUMX( Order , Order[Volume] * RELATED( Product[Price] ) )
这个案例中 SUMX 就做了坏事了。
业务人员想算销售额,而订单中没保存单价,但可以从与订单关联的产品表中找到单价,那么销售额的计算就可以是:
这个坏事就很坏了,没有 SUMX 只有 SUM 就很难受。
此外,SUMX 还可以做很多坏事,例如:
【DAX 系列】总计行问题终极解决方案 中大量使用了 SUMX。
去 ↑ 挑战下脑力吧。
如果迭代一层没有让你晕菜,请看二层迭代:
左边每迭代一步,右边与之对应要迭代一轮。
典型应用就是 ABC 分析:
ABC分析 中有这样的累计度量值:
KPI % =
VAR vCurr = [KPI]
VAR vItems = FILTER( ALLSELECTED( Model_Product[子类别] ) , [KPI] >= vCurr )
RETURN CALCULATE( [KPI] , vItems ) / CALCULATE( [KPI] , ALLSELECTED( Model_Product ) )
出图如下:
其中,上面的折线就是一个积累占比,其逻辑如下:
这就是比当前元素大的积累元素的 KPI 占比%。
构成了 ABC 分析中的 % 折线。
很明显,我们有时候在多层迭代时,需要用内圈迭代的元素(黄色)来和外圈迭代的元素(绿色)进行对比,这就需要 EARLIER 了,其含义为更早的迭代,精确讲是更早的迭代中的行。
当我们脑子绕不过来的时候,我们永远可以这么做:
VAR vCurrKPI = [KPI] // 绿色元素
VAR vItems = FILETER ( SomeTable , [KPI] ? vCurrKPI )
其中,FILTER 会创建一个内圈迭代环境,那么 [KPI] 就是内圈的黄色值,而 vCurrKPI 就是外圈的绿色值。
现在就应该可以充分理解什么是迭代器了,那么我们可以看得见它吗?看不见。
原因如下:
我们说到了迭代器是用来迭代的,迭代是用来干坏事的,如果光迭代不干坏事,那不是白迭代了。但是到底干什么坏事呢,有很多种坏事,例如:
因此,我们可以发现:迭代 + 干坏事是不可分割的整体。
因此,在 DAX 中,所有带有需要处理集合中元素语义的功能都是干坏事,都内部包裹了一个看不见的迭代器。
迭代,是很自然的。当你的业务逻辑涉及到对一堆元素(如:表行)进行遍历并在每一步都做点坏事的时候,一定会自然而然地用到某些函数,这些函数自然而然的都包裹了一个看不见的迭代器。
记得,在迭代的时候做坏事,不做坏事,DAX 不爱。
祝你玩得开心。