PowerBI之DAX神功:第1卷第14回 同表多層巢狀上下文EARLIER與VAR
2022-01-03由 孫興華zz 發表于 農業
行與列交叉形成的格子稱為什麼
EARLIER 函式提取本行對應的該列的值,實際上就是提取本行和引數列交叉的單元格。返回:當前行上下文的行值
例如:第2行是當前行,那B列的當前行就是紅色格子
現在我們看一下案例:表名是Shee1
需求:取下一行的銷售日期
下一行日期 = sumx(FILTER('Sheet1','Sheet1'[序號]=EARLIER('Sheet1'[序號])+1),'Sheet1'[銷售日期])
// 這個知識我們在《火力全開》筆記10.Earlier函式【當前行】 已經詳細講過了
但是,你要區分:下一行日期與下一個日期的區別
下一個日期 = nextday('Sheet1'[銷售日期])
//《火力全開》筆記27.4,下一個日期指的是指定日期的第二天,但是與當前表中日期總數有關,《火力全開》中做過詳細解釋
很多網友在學習了《火力全開》第10課以後,想不通,為什麼這一次的sumx不能寫在度量值裡面。
【新建列】下一行日期 = sumx(FILTER('Sheet1','Sheet1'[序號]=EARLIER('Sheet1'[序號])+1),'Sheet1'[銷售日期])
sumx建立行上下文,它是可以放到度量值中的,但是這裡,因為使用了EARLIER函式,由於當前行EARLIER函式只在行上下文中才有意義,篩選上下文中沒有當前行的概念,所以並不是sumx不能放到度量值中,而是EARLIER函式不能放到度量值中。
這件事我們先放一放,我們先舉個簡單的例子:
《The Definitive Guide to DAX》書中有這樣一節課:理解Filter、ALL和上下文互動,這裡講的東西,真的是把我整蒙圈了。
例如:有一張表,名字叫Sheet2
計算男生人數,寫一個度量值:
男生人數 = countrows(FILTER('Sheet2','Sheet2'[性別]="男"))
放到矩陣中:
這個時候不顯示王五是正常的,因為王五是女生,我們是透過filter將男生的表篩選出來,對男生的表統計行數,所以這裡面沒有王五。
當我使用切片器篩選男同學時:
當我使用切片器篩選女同學時:什麼都不顯示了
《The Definitive Guide to DAX》書中的解釋:它有兩個上下文,一個是Filter行上下文的篩選,另一個是外部切片器的篩選上下文。然後就開始不停地飆專業術語。
我發現一個問題:
假設,我現在用的尿壺(只是舉例,大多數人已經不用了),我讓你摸,你肯定不摸,你嫌髒。如果我是秦朝的人,兩千年後有一天,你挖坑將我的尿壺挖出來了,可能你會拿它當成寶。你覺得它是古董,我覺得它只是一箇舊的尿壺。
同樣的道理,用大白話講出來的東西往往不如用專業術語講得更高大尚,無論專業術語你是否能聽懂,似乎就是看專業術語沒聽懂也覺得自己很牛。我現學現賣,既然大家喜歡聽離生活比較遠的東西,那麼講原理時,我儘量少用地球上的事情來講。
塞伯坦星球上面有兩夥變形金剛,分別是霸天虎和汽車人
現在,我只看霸天虎這一部分,相當於是從塞伯坦星球上篩選出霸天虎的成員名單。
接下來,我要在霸天虎的成員名單中找擎天柱和大黃蜂。你說說看:我為什麼找不到呢?
女生為什麼篩選為空,不就明白了嗎?
現在我們思考幾個問題:
【1】我們想取Sheet2這張表中所有人員的總數:
總人數固定值=calculate(countrows(‘Sheet2’),all(‘Sheet2’))
【2】我想取Sheet2這張表男生人數的固定值:
男生人數1 = Calculate(Countrows(filter('Sheet2','Sheet2'[性別]="男")),all('Sheet2'))
【3】但是上面的公式太囉嗦,它的等效公式:
男生人數2 = Countrows(FILTER(ALL('Sheet2'),'Sheet2'[性別]="男"))
原理就是推導的過程,有必要知道它是怎麼推匯出來的,因為:
道生一,一生二,二生三,三生萬物
你理解了道理,就學會了舉一反三,但是在使用中,你不需要所有的事情都從頭推一遍,我們記住了結果,就可以使用結果,如果你只背結果,思維永遠得不到鍛鍊,這就是有些人數學考試中使用公式考出高分,但是參加工作後完全無用武之地的原因。
現在我們迴歸正題:如何將表Sheet1的【新建列】寫成【度量值】
表名:Sheet1
【新建列】下一行日期 = sumx(FILTER(‘Sheet1’,‘Sheet1’[序號]=EARLIER(‘Sheet1’[序號])+1),‘Sheet1’[銷售日期])
寫成度量值:
【度量值】下一行日期 = sumx(FILTER(all(‘Sheet1’),‘Sheet1’[序號]=SELECTEDVALUE(‘Sheet1’[序號])+1),‘Sheet1’[銷售日期])
先回憶一下Selectedvalue的作用:
為什麼Filter第一引數要加all?
因為新建列中的sumx是沒有篩選功能的它只是建立行上下文,
但是將sumx放到度量值中就具有了篩選功能
我們現在的度量值,是要體現當前行的作用,所以要取消篩選
剛才我們已經透過公式推導了filter+all的演變過程
這是整個的推導過程,也是原理的生成過程。
《The Definitive Guide to DAX》書中將EARLIER當前行函式說的一無是處,它建議用VAR函式代替,這個問題我早在2020年6月《孫興華講PowerBI重製篇》中就做了講解。沒有書中說的那麼誇張,你想用哪個都可以。
例如:將新建列寫成VAR函式
【新建列】下一行日期 = sumx(FILTER('Sheet1','Sheet1'[序號]=EARLIER('Sheet1'[序號])+1),'Sheet1'[銷售日期])
改寫成:
新建列 =
var x=‘Sheet1’[序號]
return
sumx(FILTER(‘Sheet1’,‘Sheet1’[序號]=x+1),‘Sheet1’[銷售日期])
我們使用VAR變數時,就相當於指定了當前行,只是隱藏了當前行函式而已。
當你將它改寫成度量值時,仍然注意我們提到兩個問題:
filter+all 與 selectedvalue
【度量值】
下一行日期 =
var x=SELECTEDVALUE(‘Sheet1’[序號])
return
sumx(FILTER(all(‘Sheet1’),‘Sheet1’[序號]=x+1),‘Sheet1’[銷售日期])
不顯示總計,老規矩:IF+HASONEVALUE
下一行日期 = var x=SELECTEDVALUE('Sheet1'[序號])
return
if(HASONEVALUE('Sheet1'[序號]),sumx(FILTER(all('Sheet1'),'Sheet1'[序號]=x+1),'Sheet1'[銷售日期]))
《火力全開》筆記10。Earlier函式【當前行】
我們還有其它3個案例,當時只是用Earlier函式做了新建列
現在你們可以使用VAR變數做新建列,再利用filter+all 與 SELECTEDVALUE 組合做度量值
《DAX神功》影片版同步在今日頭條和西瓜影片連載
https://www.ixigua.com/6976409163886756383