DAX学习之理解上下文

DAX圣经第二版出世后,一直想要用心读一遍查漏补缺。事实证明体系化的阅读是非常有必要的。读完第四章,对于计算上下文的理解既轻松又简单。本文会阐述当前我对DAX计算上下文的理解,做此记录,希望共有裨益。

DAX中存在计算上下文、行上下文、筛选上下文,初学者往往晕头转向不知众博客所云。这些上下文是DAX后续计算的脉络,如人体动静脉,不懂上下文就无法理解函数的运行奥秘,只能死记硬背背了又忘。

所谓计算上下文,依我理解就是DAX的计算环境,我有一个数据模型,数字们在函数中是如何组队形成最终结果的,这整个一环境就是计算上下文。而计算上下文主要就分为行上下文和筛选上下文两种。也就是说,一个函数怎么计算,关注其和行上下文的关系,和筛选上下文的关系,计算环境就大致告成了。

一、谈谈行上下文

谈到行上下文,有些同学就会想到,在报表前端拉一张数据表或是矩阵表,指着其中的行列就说,这是行上下文。对吗,当然不对。

从数据角度来说,一切报表前端的内容都是表象,我们真正在使用的是我们的基础表,是数据模型中的表,是构成表关系的表。

所以计算的本质,在于计算我们的基础表。行上下文作为计算上下文,也就是计算环境中的一大组成部分,其针对的对象自然也是我们的基础表。行上下文就是对基础数据表的遍历。给没学过变成的同学解释一下什么是遍历:我有一百行数据,我每行数据都读了一遍,这就是遍历。

什么时候会出现行上下文呢?有两种情况。

①列计算的时候,行上下文就会自动出现。其实也很好理解嘛,你增加了一个新列,可不得每行都走一遍,才能说新建了一个列。一个新建列中,不能出现一个“黑洞”行吧:)

②度量值计算的时候,需要我们加入迭代器,行上下文就会出现。迭代器,可以理解为把基础表每一行都遍历一遍的工具。举个例子,基本所有带X的函数,本质上都是个带特殊技能的迭代器。比如SUMX:

Sales Amount = SUMX (Sales, Sales[Quantity] * Sales[Price] )

--注释:Sales表中, 存在Quantity列和Price列。对每行数据都进行 [Quantity] * [Price]的计算,此时存在一个新的虚拟列,用于存放每行[Quantity] * [Price]的结果值。将这个虚拟列进行求和。

在上面的这个例子中,我引进了一个虚拟列的概念,便于各位理解。其实和①中相似了对吗,只要需要对行数据产生新值或是计算(计算值也是新值),那么不管你是真实列还是虚拟列,都产生了行上下文。

值得注意的是,行上下文只和单表对象有关。如果A表和B表是一对多的单向关系,A表发生行上下文,也就是A表被遍历和迭代了,这对B表有影响吗?

答案是没有。因为遍历存在于一张表中。举上面的例子,假设A表中有Quantity列和Price列,我对这两列进行SUMX的遍历求和,虽然B表和A表存在关联关系,但针对列的遍历是无法跳到B表上去执行的。

那如果A表有Price列,B表有Quantity列,我们有需求对A表和B表进行同时遍历怎么办?一种同学会想,那我在一开始导入数据时,对A表和B表做left join的关联查询呀,把B表的Quantity列取到A表中,就又可以在一张表中执行遍历了。这是一种方案,但如果我们在建模时已经做好了A表和B表的一对多单向关系,不妨直接用DAX函数进行关联取列。

我们引入Related和Relatedtable这两个函数,解决该问题。这两个函数通常也是为了实现多表间的行上下文存在的,即实现多表间的同时迭代。从函数名的字面理解看,我们大致也能猜到,Realtedtable返回的是一张表,那么相对应的,Realted返回就是一个单值。这是为了匹配我们关系中的一对多和多对一而存在的。

在上面的例子中,我们已经假设A表和B表是一对多的单向关系,A是一端,B是多端。也就是说,一个A表值可能对应到多个B表值。那么从A表出发,我们使用关系函数的时候,B表应该返回多值,是一张表的形式,所以在这个例子中,我们应该使用Relatedtable(B)。

二、谈谈筛选上下文

筛选上下文其实也很好理解,就是筛选嘛。你这计算环境中存在筛选吗,这也是DAX计算时需要考虑的事情。

PBI表格

大家可能觉得,筛选嘛,还能不认识啊。别说,真有人不认识,以上PBI表格中,有哪几个筛选?筛选上下文中的筛选,和我们狭义的筛选并不一致,除了切片器,页面级筛选、报表级筛选,还存在行筛选、列筛选。如上图所示,2016、2017、苹果、三星、小米,这都是筛选器。我们的度量值只有一个sum,但我们的结果却被这些行和列分割得七七八八。

值得注意的是,筛选上下文是早于DAX计算的。也就是说,在公式计算之前,筛选上下文就已经发挥作用了。比如上图中第一个计算格中的15574.7是怎么来的?在“年”=2016年和“品牌”=苹果的数据中,我去计算销售总和,得到15574.7。

上面我们讲了行上下文只作用于单表对象,作用到其他表时,我们需要用到关系函数才可以实现。筛选上下文的作用对象是什么呢?答案是数据模型。也就是说,只要A表和B表存在关系,且关系可以正向流通,那么筛选就会自动传递。

三、一个实例(嵌套行上下文)

一个非常好玩的例子,如果我们不会用Rank函数,我们该如何求出销售经理的销量排名。思路是,找出比我销量高的销售经理,他们的人数+1就是我的排名。以下是我们的DAX demo:

Rank =

VAR CurrentPersonAmount = Sales[Amount]

VAR PersonBeforeMe = CountRows(Filter(Sales[Amount],Sales[Amount]>CurrentPersonAmount))

Return PersonBeforeMe+1

这边涉及两个迭代,一个是新增Rank列时,PBI会自动产生一个行上下文,得到这个行上下文作用的是变量CurrentPersonAmount,也就是说,变量CurrentPersonAmount中的Amount值,会自动遍历一遍Sales表。

而第二个迭代,其实是嵌套在第一个迭代中的,由Filter产生。Filter是个带特殊功能的迭代器,他会对Sales表中的Amount列,逐个进行遍历。

可能有些同学没听懂,我把内部发生的事情再阐述一遍:当CurrentPersonAmount处于Sales表的第一行时,执行一次变量PersonBeforeMe的计算,此时变量PersonBeforeMe中CurrentPersonAmount的值,依旧是第一行的Amount,但PersonBeforeMe中的Sales[Amount],将会遍历一遍Sales表,这是Filter这个迭代器发挥的作用。这边会依次选出大于第一行Amount值的所有Amount值,以便返回第一行Amount前面有几个比他大的Amount。

这样,第一个Amount的排名就基本确定了,接下来,CurrentPersonAmount跳到Sales表的第二行,再次执行变量PersonBeforeMe的计算,以此类推。

总结一下,被嵌套的行上下文,如果需要引用外部行上下文的内容,可以用变量的形式进行传递。

一个小检测,此时的你,能理解earlier函数的含义了吗?提示,earlier函数就是为了引用外部行上下文的内容而产生的函数。。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容