計算上下文是計算公式的環境,任何DAX表達式都是在上下文中求值的。行上下文和篩選上下文是DAX中僅有的上下文類型,把這兩種上下文稱為計算上下文。計算上下文用於限定公式計算的環境,當上下文變化時,相同的公式會計算出不同的結果。
一,計算上下文
在PowerBI中創建的計算列是在行上下文中執行計算,創建的度量(meassure)是在篩選上下文中執行計算。
- 行上下文是一個總是包含一行的上下文,DAX在創建計算列時自動定義行上下文。
- 篩選上下文是由切片器(Slicer)、用戶選擇的分組字段、關系的篩選方向等過濾器共同定義的,而DAX利用篩選上下文來計算公式(度量)。
二,行上下文
行上下文僅僅存在於表的同一行中,作用是對表中同一行的不同列,應用公式,逐行計算出公式的結果。
例如,創建一個計算列 Profit,利潤的公式是由商品的 銷售額 - 稅額 - 成本 - 運費,DAX公式如下所示:
Profit = FactSales[SalesAmount]-FactSales[TaxAmt]-FactSales[TotalProductCost] - FactSales[Freight]
DAX逐行應用公式,對於表中每一行,都會根據公式,把同一行上的不同列的值代入到公式中,計算出公式的結果:
實際上,用於執行計算的行並沒有存儲在公式中,而是定義在行上下文中。從邏輯的角度來講,計算列的工作流程是:
- 當你定義計算的列時,DAX從表的第一行開始迭代,首先創建了包含該行的行上下文並對表達式求值,
- 然后它移到第二行,再次求出表達式;
- 這發生在表格中所有的行中,如果你有100萬行,你可以認為DAX創建了100萬行上下文來評估這個公式100萬次。
三,篩選上下文
1,自動應用篩選上下文
Measure SumOfAccount = CALCULATE(SUM(FactSales[SalesAmount]))
為該度量增加一個分組列FullName,可以看到,這個分組列對度量的上下文進行過濾,使其只能計算每個FullName對象的銷售額,而度量自動應用篩選之后的上下文,計算每個FullName的銷售額:
FullName是DimCustomers表的字段,該字段能夠自動過濾FactSales表的原因是在數據模型中,表DimCustomers和表FactSlaes之間存在關系,並且關系的方向是由DimCustomer指向FactSales,這說明,DimCustomers可以過濾FactSales:

2,關系的方向
當關系的方向是由A指向B時,說明A可以篩選B,而B不能用來篩選A。上圖中,表DimCustomers和表FactSlaes之間存在關系,並且關系的方向是由DimCustomer指向FactSales,這說明,DimCustomers可以過濾FactSales。我們來測試一下,FactSales是否可以篩選DimCustomers?創建一個新的度量,測試使用FactSales的ProductKey來統計用戶的數量:
Measure CountCustomer = CALCULATE(COUNT(DimCustomers[CustomerKey]))
測試的結果是 Measure CountCustomers的值是DimCustomers表的總數量,也就是說,ProductKey不能過濾DimCustomers表。
當把DimCustomer和FactSales之間的關系修改為雙向時:
用於FactSales可以過濾DimCustomers,DAX自動應用篩選上下文,統計每個ProductKey對應的客戶數量:
3,修改、清除和重定義篩選上下文
使用DAX函數可以修改、清除和重定義篩選上下文。CALCULATE()函數是DAX中最復雜的函數,用於計算由指定過濾器修改的上下文中的表達式。CALCULATE(<expression>,<filter1>,<filter2>…)
第一個參數是用於計算聚合值的度量,后面的參數是可選的過濾器,共有兩種類型:
- 返回布爾值的邏輯表達式
- 返回表的表達式
CALCULATE函數的復雜之處在於可變的數據上下文。如果數據已被過濾,則CALCULATE函數會更改過濾數據的上下文,並在您指定的新上下文中計算表達式。 對於filter參數中使用的每個列,將刪除該列上的任何現有過濾器,並應用filter參數中使用的過濾器。
參考文檔: