DAX從入門到精通?5-2-1 Calculate案例

現(xiàn)在你已經(jīng)學(xué)些了calculate的基礎(chǔ)知識,或至少你已經(jīng)知道它為何如此重要,章節(jié)的剩下部分我們提供了大量的案例。它們非常有益于我們學(xué)習(xí)。calculate函數(shù)本身很簡單,它的復(fù)雜之處在于,使用它必須要求我們用上下文的思路在思考,同一個函數(shù)中,可能會有多種上下文情況,這個使得理解代碼變得復(fù)雜。根據(jù)我們的經(jīng)驗,通過案例來學(xué)習(xí)calculate和篩選上下文,是非常好的方法。

單一列的過濾

calculate最簡單的使用方法是只過濾一個列。舉例,假設(shè)你要建立一個度量值,總是返回黑色產(chǎn)品的銷售額,而不去考慮選擇了什么顏色,函數(shù)可以這樣寫:

[SalesAmountBlack] :=
CALCULATE (
SUM ( Sales[SalesAmount] ),
Product[Color] = "Black"
)

如果你使用了這個函數(shù),會得到如下的:


image.png

可以看到,新列總是顯示黑色產(chǎn)品的銷售額,即使每行的篩選條件是不同的顏色.

如果你把注意力集中在第三行 blue,它的值是這樣計算的:函數(shù)讀取了當(dāng)前的篩選上下文,有就是藍色。然后,calculate生成了一個新的條件--黑色,接著這個這個黑色的篩選條件替代了原始的篩選條件,然后計算表達式,最后把結(jié)果展示出來。其他行也是這樣計算的。

顯然,因為我們只是改寫了color的篩選,其他列的還是保持原有的篩選條件。例如,如果你把calender year放到列中,你會看到所有的顏色相同年份都是一樣的值,只有不同年份的時候,才有差別。

image.png

只過濾一個列,是很簡單直接的。一個特點是如果你使用條件判斷的方法,那么一次只能過濾一個列。例如,如果你要建立一個度量值,來計算那些unit price至少是 unit cost兩倍的產(chǎn)品的銷售額,可以試一下下面這個例子:

[HighProfitabilitySales] :=
CALCULATE (
SUM ( Sales[SalesAmount] ),
Product[Unit Price] >= Product[Unit Cost] * 2
)

可以看到,這次,條件判斷引入了兩個列:unit cost和unit price。即使DAX可以很容易的判斷每個產(chǎn)品的這個條件,但是這樣的寫法是不對的。原因是,在判斷寫法的時候,calculate無法判斷這個新的條件是要替代已有的unit price篩選器,還是unit cost篩選器,或者兩者。所以,如果你按這樣的寫法,結(jié)果是一個報錯的。

Calculation error in measure 'Sales'[HighProfitabilitySales]:
The expression contains
multiple columns, but only a single column can be used in a
True/False expression that is
used as a table filter expression.

對于這樣的情況,沒有任何使用布爾值的函數(shù),如果你要在calculate中的條件判斷引入多個列,那么你需要使用另外一種寫法,也就是提供一些列的值,而不是用條件判斷的方式。

上面案例的正確寫法是這樣:

[HighProfitabilitySales] :=
CALCULATE (
SUM ( Sales[SalesAmount] ),
FILTER ( Product, Product[Unit Price] >= Product[Unit Cost] *
2 )
)

這次不適用一個布爾表達式,而是在過濾參數(shù)中使用列表的方式。另外,我們不止過濾了一列,我們過濾了整個product表。在下圖中,我們可以看到,HighProfitabilitySales可以正常工作。

image.png

這時候,calculate這樣工作:filter的結(jié)果包含了多個列(這里是包含了product表的所有列),當(dāng)這個新的條件添加到篩選上下文的時候,所有之前在product表存在的篩選條件都會被替換。換句話說,當(dāng)在filter函數(shù)中第一個參數(shù)是表的時候,產(chǎn)生的結(jié)果就是替換該表所有的篩選條件。

有了之前的解釋,我們會觀察到有個地方?jīng)]有完全的介紹清楚。我們說filter表達式替換了product表所有的篩選條件,因為filter返回的表包含了所有的product的列。但是,每行我們返回的值都是不一樣的。

在行blue中,highprofitabilitysales返回的是藍色產(chǎn)品的計算值,按我們所學(xué)的,不是應(yīng)該忽略顏色返回所有產(chǎn)品函數(shù)條件計算的值么?因此,我們要花費一些時間,來認(rèn)真的看下,上下文的計算順序是怎么樣的。下面這個代碼是我們度量值使用的,每行都寫了編號,便于我們定位函數(shù)的某部分

1. CALCULATE (
2. SUM ( Sales[SalesAmount] ),
3. FILTER (
4. Product,
5. Product[Unit Price] >= Product[Unit Cost] * 2
6. )
7. )

一開始是函數(shù)calculate,然后是計算表達式,這個都很簡單,函數(shù)的篩選條件開始于第三行 filter。

filter是一個迭代函數(shù),它在product表迭代,也就是第四行。此時的filter不會看到所有的行,它篩選的行是在當(dāng)前上下文環(huán)境下看到的。問題來了,第四行中,是在哪個篩選上下文環(huán)境下?記得,calculate還沒有創(chuàng)建新的上下文。它要后面才會產(chǎn)生。所以,它的上下文是在原始的篩選上下文產(chǎn)生的而不是calculate產(chǎn)生的。雖然有點繞口,但是這個簡單的思考順序,是很多DAX函數(shù)產(chǎn)生問題的點。

第四行的產(chǎn)品,是在原始的篩選上下文環(huán)境下生成了。對于blue的產(chǎn)品,product只有看到blue的產(chǎn)品,因此,filter只會迭代blue的產(chǎn)品,然后選擇high profitability的產(chǎn)品。然后,calculate會移除color上的篩選條件,但是這個條件已經(jīng)應(yīng)用到之前的filter結(jié)果中了,也正如我們看到的。所以正確的理解filter的順序非常重要,過濾是是被calculate產(chǎn)生的篩選條件替換的,而不是在calculate中的的filter函數(shù)替換。換句話說,calculate的filter參數(shù)的上下文環(huán)境是之前的原始上下文。而當(dāng)calculate計算產(chǎn)生了新的上下文環(huán)境后,calculate根據(jù)新的環(huán)境計算表達式。

通過下面這個函數(shù),可以有個完整的理解:

[HighProfitabilityALLSales] :=
CALCULATE (
SUM ( Sales[SalesAmount] ),
FILTER (
ALL ( Product ),
Product[Unit Price] >= Product[Unit Cost] * 2
))

這次,我們使用all(product)作為filter的表的參數(shù)。filter迭代的就不只是blue的產(chǎn)品,它總是迭代整個產(chǎn)品表,因為calculate會替換原始的篩選條件,所以我們會看到下面整個表:

image.png

HighProfitabilityALLSales 總是顯示所有high profitability的產(chǎn)品,完全的忽略了在color上存在的過濾條件。我們可以總結(jié)下整個例子。

你可以在calculate中使用布爾表達式,但是,這時候,你只能引用單個列,如果引入了多列,那么系統(tǒng)會報錯。

你可以使用filter或者其他的表函數(shù)作為calculate的參數(shù)。這時候,所有的列都是新的篩選上下文的組成部分。也就是calculate會替換這些列已經(jīng)存在的篩選條件。

如果你是用了filter,那么filter使用原始的篩選上下文作為其篩選條件。如果你使用的是布爾表達式,那么calculate會替換該列現(xiàn)有的篩選上下文。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容