CALCULATE函數應該算是DAX語言中用的最廣,最神奇,也最容易了解出錯的一個函數。它具有重新設定篩選上下文,并且将行上下文轉換為篩選上下文的能力。
在DAX函數中,絕大多數函數的執行順序都是從左到右依次進行,例如SUMX函數
SUMX(<table>,<expression>)
,如果table參數處使用了一個可以傳回表單的表達式,則在運作時Power BI會先将這個表單表達式的結果計算出來,之後再計算expression參數部分。而CALCULATE函數
CALCULATE(<expression>,<filter1>,<filter2>…)
則很特殊,Power BI會先對後面的filter參數部分進行計算,之後才會運作expression表達式部分。
CALCULATE函數這種獨特的從“右”到“左”的運算順序會對運算結果産生什麼樣的影響呢?且看下面這個表單例子。
如果建立下面這個路徑成本C1來計算France的産品銷量,猜猜會有什麼樣的結果。
C1 =
CALCULATE (
[TotalSales],
'Sales SalesTerritory'[Name] = "France"
)
hmm,一般覺得應該隻有France這一行有相應的計算結果,而其他國家對應的值都是空?但其實結果如下圖所示:
對比第一張圖的原始資料,France這一行的計算結果是沒有問題的,但是其他國家的值也都被賦予了France的對應的銷量值。
之是以出現這樣的結果就是跟CALCULATE函數的篩選表達式使用布爾函數時,其含義相當于調用了FILTER函數并使用了ALL函數作為FILTER函數内的篩選條件。按照這個邏輯,前面的C1表達式等同于下面這個包含C2表達式:
C2 =
CALCULATE (
[TotalSales],
FILTER (
ALL ( 'Sales SalesTerritory'[Name] ),
'Sales SalesTerritory'[Name] = "France"
)
)
之前說過,CALCULATE函數的計算順序是從“右”到“左”,是以Power BI在對C2進行運算時,會先計算FILTER函數部分。FILTER裡面有一個超級無敵去篩選條件的ALL函數,是以在這個函數的作用下,外面的篩選上下文對計算結果都将起不到過濾作用。此時,FILTER函數的傳回結果變成了隻包含’Sales SalesTerritory’[Name] = "France"的子表單,這樣,内嵌路徑成本[TotalSales]的計算範圍就被限定到了隻針對France列資料進行聚合,是以無論外圍可視化表單設定了何種篩選條件,C1和C2都隻會執着的顯示8119749.346這個結果。