什麼是計算列、什麼是度量值
計算列是直接在現有的表上添加一個新列,
新建的計算列,和表中之前已經存在的列一樣,可以作爲表格的行、列,圖表的軸以及切片器的字段等等,也可以使用計算列與其他表建立關係。
而度量值,如果不放到上下文環境中,它就是一個孤立的公式,並沒有視覺上的計算結果,因此,很多人會覺得度量值比較難以理解,尤其是Excel用習慣的人,都會傾向於使用計算列。
字段標識不同
如下圖的字段面板
倒數第二個字段,前面有fx符號,代表的是計算列;而最下面一個,前面是個計算器的標識,表明[最後訂單日期]是一個度量值。
怎麼寫計算列、怎麼寫度量值?
這個纔是大家更關注的問題,也是平時容易出錯的地方。下面以一個實例來介紹計算列與度量值的寫法有什麼不同。
以這個簡化的訂單表爲例,如何計算出每個客戶的最後下單時間?
計算列的寫法
不少人也許直接這樣寫,
結果都是訂單表中最後一個訂單日期,顯然與我們的期望不符,爲什麼會這樣呢?
計算列的上下文就是當前行,但是MAX函數(包括SUM、MIN等聚合函數)並不能將行上下文轉化爲篩選上下文,也就是說當前行沒有起到篩選作用,它就會返回整個表的最大訂單日期。
關於上下文,不要理解的太複雜,完全可以按中文字面意思來理解,簡單來說就是當前的計算環境,一般分爲行上下文和篩選上下文,行上下文可以簡單的理解爲當前行,行上下文並不會必選產生篩選作用,只有篩選上下文才會產生篩選作用,篩選上下文有很多種形式,比如表格的當前行,矩陣的行和列、圖表的座標軸、報表的切片器、篩選器等。
如何讓當前行發生篩選作用呢?在MAX函數外圍再套個CALCULATE函數就可以了,
這樣返回的下單日期都不同了,但是仔細看就會發現,返回的日期和當前行的下單日期是一樣的,並沒有按照客戶進行計算。
再強調一遍,計算列的上下文就是當前行,包括當前行的每一個值,在上表中,每一行的數據是唯一的,因此只能返回當前行的訂單日期。
那麼到底如何按照客戶來計算,返回當前客戶的最後下單日期呢?
解決這個問題的DAX寫法有很多種,這裏用個相對簡潔的代碼,
ALLEXCEPT函數的意思是,清除訂單表其他列的篩選作用,只保留客戶列的篩選,這樣當前行的上下文,其他列的篩選作用清除了,只有客戶發生篩選作用。
比如客戶甲,有兩筆訂單,使用MAX計算出最大的訂單日期,也就是甲的最後下單日期。
上面說了這麼多計算列的寫法,那麼度量值該怎麼寫呢?
最後下單日期=MAX('訂單表'[訂單日期])
是不是簡單到不敢相信,那麼如何看到計算結果呢,最簡便的方式就是直接用個表格或者矩陣展現結果,
再舉個例子,依然是這個訂單表,如何計算每個產品的最後賣出日期?
如果你理解了上面計算列的原理,這個問題是不是也很容易就出來了,
那麼度量值又是如何寫才能解決這個問題的呢?
其實度量值的寫法可以完全不變,依然可以用上面的代碼(MAX('訂單表'[訂單日期]),只要把表格的維度改爲產品名稱就可以了,
通過上面兩個問題,你看出來計算列和度量值有哪裏不同了嗎?
在計算列中,其上下文是明確的,就是當前行,並且可以根據需要縮小爲當前行的某一列;
而度量值,編寫時並沒有明確的上下文,度量值寫好之後,可以放在任意的上下文環境中,執行不同的計算;
計算列寫好代碼,數據自動計算出來,並且不受外部篩選器的影響;
而度量值寫好之後,並沒有立即計算,只有放到上下文中時,才進行計算並返回結果。
所以利用DAX解決問題時,首先應想到上下文是什麼,新建列時如何利用當前行的上下文?
而度量值雖然暫時沒有上下文,但在建度量值之前,也首先應該想清楚,我需要構建怎樣的上下文環境才能得到期望的結果,然後利用心中所想的上下文環境,來對應的編寫度量值的DAX代碼。
在PowerBI中,除了計算列和度量值,還有個地方可以用到DAX,就是使用DAX新建表,
使用建表的方式同時可以解決上面的問題,
其中VALUES('訂單表'[客戶]),返回客戶的不重複列表,就是爲了給後面的代碼提供上下文,有了這個上下文,後面的代碼與新建列的寫法是一樣的。
通過這三種使用DAX的環境,以及上面的幾個例子,應該能發現,無論是度量值、計算列還是建新表,其DAX代碼本質上並沒有什麼不同,不同的只是下上文而已。
計算列只能利用當前行上下文;新建表可以使用DAX構建上下文;’而度量值最靈活,先不管上下文,寫好代碼之後,給什麼上下文,就執行什麼運算,或者說需要什麼計算,就給度量值提供什麼上下文。
你以後再遇到問題打算用DAX實現,一定要先想清楚,是通過計算列、新表還是度量值來解決,然後再開始寫對應的DAX。
計算列和度量值寫法的不同點
關於計算列和度量值在寫法上有一些不同,比如在計算列中使用列,可以直接使用,默認就是該列的當前行,比如返回當前訂單日期的前一天,可以直接寫:
而在度量值中使用列,必須在列上套一個聚合函數,否則不能自動轉換爲篩選上下文,計算訂單日期前一天的度量值應該這樣寫:
訂單日期前一天 = MAX('訂單表'[訂單日期])-1
什麼時候使用新建列,什麼時候使用度量值
一般來說,爲了性能考慮,能用度量值解決的問題就儘量不用計算列(參考:高效使用Power BI的15條建議)。
只有當你需要利用新建的計算列生成切片器(度量值不能用於切片器),或者需要用這個字段與其他表建立關係時,才需要新建列。
另外當需要創建很複雜的字段時,儘量使用計算列,因爲它需要時間來運算,提前運算完成,而不是在需要用的時候再進行計算(度量值是用的時候才計算),可以帶來更流暢的體驗。
總結
計算列和度量值在DAX代碼的寫法上並沒有本質不同,形式上的不同只是由於上下文環境的區別引起的。
二者的本質不同在於其運算特點,是否根據上下文動態運算、以及計算時間上的不同,纔是根本的差異。
-精彩推薦-
採悟 from PowerBI星球