https://zhuanlan.zhihu.com/p/64382849
介紹DAX的時候,特別強調過一個重要的函數:CALCULATE,本文就來揭秘這個函數的計算原理以及它是如何影響上下文的。
CALCULATE的語法結構
語法:
CALCULATE(<expression>,<filter1>,<filter2>…)
- 第一個參數是計算表達式,可以執行各種聚合運算
- 從第二個參數開始,是一系列篩選條件,可以為空;如果多個篩選條件,用逗號分隔
- 所有曬選條件的交集形成最終的篩選數據集合
- 根據篩選出的數據集合執行第一個參數的聚合運算並返回運算結果
前文提到DAX函數可以更改外部上下文,現在通過實例來理解DAX中最精髓的函數CALCULATE的計算原理,並看看它是如何更改外部上下文的。
CALCULATE應用實例
導入下面這個產品明細表:
新建一個度量值求每種產品的數量:
產品數量 = COUNTROWS('產品明細')
因為每種產品的只有1行,所以求產品明細表的行數就相當於求各種產品的數量,把產品名稱和該度量值拖拽入矩陣表,
這里外部上下文就是表格每行的行標簽。
01 | 篩選條件為空,不影響外部上下文
現在開始用CALCULATE函數創建一個度量值:
產品數量1 = CALCULATE([產品數量])
只是用了第一個參數,篩選條件為空,因為沒有內部篩選所以完全依賴外部上下文,出來的結果也和原度量值一致。
另外,介紹CALCULATE語法的時候說,第一個參數為聚合運算表達式,為什么這里沒有用聚合函數而只用了一個度量值呢?這是因為度量值[產品數量]本身就是一個聚合函數運算,實際上度量值[產品數量1]等同於這個:
產品數量1 = CALCULATE(COUNTROWS('產品明細'))
DAX函數可以直接引用已經創建好的度量值,可以使DAX函數看起來更簡潔、更具可讀性,這也是建議從最簡單的度量值開始建的原因。
02 | 添加限制條件,縮小上下文
建一個度量值[產品數量2],
產品數量2 = CALCULATE([產品數量],'產品明細'[品牌]="蘋果")
發現只有蘋果的產品計數顯示出來,而其他品牌的數據沒有了,這是因為CALCULATE的第二個參數的限制,只篩選品牌為“蘋果”的,限制了外部的上下文,非蘋果的產品都不再運算。
03 | 結合ALL函數,擴大上下文
新建度量值[產品數量3],
產品數量3 = CALCULATE([產品數量],ALL('產品明細'))
這次的數據居然是所有產品的數量,這是因為篩選條件使用了ALL函數,ALL('產品明細')的意思是清除產品明細表里的所有篩選,外部篩選器不起作用了,每行統計的都是該表中的所有產品。
每行的數據都是9,你可能覺得這個ALL函數沒什么用,運算的數據沒有什么意義,會誤導人,實際上當然不是這樣,這個數據使用的地方非常多,比如我們想計算每個產品數量占總產品數量的比重,直接寫個度量值:
產品占比=[產品數量]/[產品數量3]
產品占比就計算出來了,這就是統計總數的一個功能。
04 | 重置上下文
新建度量值[產品數量4],
產品數量4 = CALCULATE([產品數量],
all('產品明細'[產品名稱]),
'產品明細'[類別]="手機")
先用ALL函數清除外部上下文,然后又新增了一個篩選條件,類別為"手機"的產品數量,那么結果會是什么樣的呢,
每一行產品的數量都是3,正好符合建立這個度量值的邏輯,被ALL清除行標簽的外部篩選后,從全部產品中統計品類為"手機"的產品的數量,所以每行都返回3.
通過以上幾個簡單的例子,可以領會到CALCULATE的計算邏輯,通過從第二個參數開始的篩選條件,得到一個數據集合,並利用第一個參數執行聚合運算,這不就是DAX要實現的功能:提取有用數據並執行聚合運算嗎,所以說CALCULATE幾乎就是DAX本身,它就是實現DAX功能的引擎,並能靈活的操控外部上下文,后面的數據分析也都離不開CALCULATE的身影。
文中案例數據在公眾號中請回復“CALCULATE案例”下載