DAX專題8: All/RemoveFilters/AllExcept/AllSelected-讀書筆記(16)

一、ALL 函數(shù)
1?? ALL函數(shù) The ALL Function
語法:ALL( [<table> | <column>[, <column>[, <column>[,…]]]] )??
參數(shù)為表或表的列,可以把表的多個列做為參數(shù)
??作為表函數(shù)使用時,返回表中去掉重復(fù)行表,或者列(多列)的所有唯一值的表(可能是單列表)
??作為修改篩選函數(shù)使用時,清除函數(shù)參數(shù)表或表[列]的所有篩選(即忽略表中所有的篩選器)。也可以把它叫計算修改器,因?yàn)樗延嬎阒姓谟玫暮Y選條件全給拿掉了。
ALL函數(shù)是一個創(chuàng)建虛擬表的函數(shù),返回一個沒有重復(fù)行的表。
2?? ALL函數(shù)和VALUES 函數(shù)比較 ALL? Compared to VALUES
第十三章我們講過可以通過新建表把函數(shù)創(chuàng)建的虛擬表變成一個實(shí)體表。在公式欄輸入:
Product Colors All = ALL(Products[Color])

Product Colors Values = VALUES(Products[Color])

可以看到,這兩個函數(shù)返回的結(jié)果沒什么區(qū)別。但我們要注意,這兩個函數(shù)還是有很重要的區(qū)別的:VALUES返回的表是遵循模型之前的篩選上下文,ALL函數(shù)會忽略(清除)所有的篩選上下文。用這兩個函數(shù)創(chuàng)建的實(shí)體表不存在篩選上下文時返回的結(jié)果一樣,但存在篩選上下文時則結(jié)果會很不同。
我們再寫一個公式
Product Color/Category ALL = ALL(Products[Color],Products[Category])

用兩個列做參數(shù),返回一個不重復(fù)的兩列表。我們上面的幾個用法是為了測試,通常ALL是作為生成虛擬表的函數(shù)嵌套用在其它DAX公式里面的。ALL函數(shù)返回的虛擬表的行為就像模型中的實(shí)體表(從源導(dǎo)入的表)一樣在模型中與其它表產(chǎn)生關(guān)系。因?yàn)锳LL返回的表是虛擬表,我們并看不到它,這也是DAX中的表函數(shù)比較難學(xué)的原因之一。
3?? 在度量值中使用ALL函數(shù) Using ALL Inside Measures
ALL函數(shù)的通常是用在度量值中,ALL函數(shù)很有用,它可以清除來自可視化對象的篩選(VALUES返回的表是遵循模型之前的篩選上下文,ALL函數(shù)會忽略(清除)所有的篩選上下文。)
下面我們看下ALL的用法,創(chuàng)建一個矩陣,把 Products[Category]列放到矩陣行上,把之前寫的度量值 [Total Number of Products] 放在值上

我們可以看到,矩陣中第一行Accessories 并沒有篩選源表,第一行顯示的是 Product Category = "Accessories"的產(chǎn)品數(shù)量,其實(shí)在背后的工作原理跟我們用篩選按鈕選出Product Category = "Accessories"的邏輯是一樣的,只不過矩陣的篩選是悄悄地在背后進(jìn)行的。

矩陣和手工篩選出來的結(jié)果是一樣的。
NOTE: 使用手工篩選按鈕來檢查DAX公式結(jié)果是一個很好的辦法,寫出一個度量值時,我們可以通過手工篩選、計算來檢查度量值的結(jié)果是否正確。手工篩選數(shù)據(jù)表并不會影響報表的結(jié)果,它只是檢查、測試、調(diào)試和學(xué)習(xí)的一種方法而已。
矩陣應(yīng)用了行篩選(矩陣的行篩選產(chǎn)品表)以后,度量值再計算篩選剩下的表的行數(shù)做為度量值的結(jié)果。矩陣中每個值單元格的結(jié)果(包括總計)都是這樣計算出來的。因?yàn)榫仃嚨目傆媶卧駴]有行篩選條件,所以總計就是產(chǎn)品表的全部行數(shù)。你也可以手工逐個檢查計算每個單元格的篩選結(jié)果,肯定和度量值在矩陣中顯示的結(jié)果一樣。
下面我們用ALL和VALUES寫三個度量值:
total productnumber = COUNTROWS(Products)
Total All Products = COUNTROWS(ALL(Products))
Total Values Products = COUNTROWS(VALUES(Products))
NOTE:公式里ALL使用表做為參數(shù),沒有使用表的列做為參數(shù),這樣寫在ALL、VALUES函數(shù)中都可以。
ALL函數(shù)返回一個表,但這不能直接放在度量值里,可以在外面再套一個聚合函數(shù),像COUNTROWS等讓函數(shù)返回一個值。我們把度量值放在矩陣?yán)锟纯唇Y(jié)果

Products表的[Category]列被矩陣行字段篩選,度量值第二參數(shù)ALL(Products)把來自矩陣的篩選給全部扔掉了,嵌套ALL函數(shù)的度量值清除了所有篩選,返回一個固定值PRODUCT表的所有行數(shù)量,其它兩個度量值則都被矩陣篩選了。通過這個例子我們不能明白ALL函數(shù)是怎么工作的了。
4?? 在CALCULATE函數(shù)中使用ALL函數(shù)返回的表篩選條件 Using ALL as a Table Filter Inside CALCULATE
ALL函數(shù)通常用在CALCULATE函數(shù)中做為第二參數(shù)使用,就是做為CALCULATE的表篩選參數(shù),它清除所有來自可視化對象的篩選條件。ALL函數(shù)的這個功能通??梢杂迷谄渌瘮?shù)中嵌套使用。
計算每個國家銷售占總銷售的占比:
?? 我們先把國家放在矩陣的行上,把銷售度量值放在值上
在值字段右鍵度量值,--將值 顯示為--占總計的百分比。這樣做可以得到占百分比,但我們不能繼續(xù)使用這個值,比如我們想計算銷售占比大于10%的國家數(shù)量,那就不行了,我們不能在其它計算方法中使用矩陣中的這處百分比值。如果想使用百分比結(jié)果,我們得寫個度量值

5?? 如果想使用百分比結(jié)果,我們得寫個度量值
用ALL函數(shù)寫個度量值 Writing Your Own DAX Measures by Using ALL
第一步:總計度量值
Total Global Sales =
? ? CALCULATE([Total Sales], All(Territories))
第二參數(shù)返回Territories表的所有行,并清除矩陣的所有篩選
第二步:百分比度量值
% of Global Sales =
? ? DIVIDE([Total Sales], [Total Global Sales])

兩個練習(xí)
??Create a Grand Total Measure
Total Global Sales =
? ? CALCULATE([Total Sales], All(Territories))
??Create the Percentage of Total
% of Global Sales =
? ? DIVIDE([Total Sales], [Total Global Sales])

6?? 快速度量值 Using the New Quick Measure Option
在矩陣值字段的某一度量值上右鍵,會彈出一個快速度量值子菜單,你可以不需要掌握什么DAX知識就能使用快速度量值。使用快速度量值比使用隱式度量值更好,您可以重命名快速度量值、編輯度量值、格式化度量值以及在其他度量中重用快速度量值。
??假如你要創(chuàng)建一個快速度量值,用于計算一個類別的總數(shù)。在新建快速度量值向?qū)е?,你需要做的就是將一個列或度量值從右邊的字段列表拖到左邊的相關(guān)區(qū)域中。本例中,將[Total Sales]度量值添加到Base Value值,將[Country]列添加到Category。
NOTE:快速度量值可以做為我們學(xué)習(xí)DAX的一個輔助工具,實(shí)際使用中還是建議大家使用DAX自己編寫公式。
7?? 在ALL中使用表或列 Passing a Table or a Column to ALL()
需要注意的是:在上面的例子中,我們使用另一種寫法也能得到相同的結(jié)果,這次我們這樣寫
Total All Country Sales =
? ? CALCULATE(
? ? ? ? [Total Sales],
? ? ? ? ALL(Territories[Country])
? ? )
度量值第二參數(shù)ALL的參數(shù)是一個列。但是這個度量值在矩陣的行字段不是Territories[Country]時,結(jié)果就又變了。你可以對比一下下圖中矩陣的第四列

二、REMOVEFILTERS 函數(shù)
Several times so far in this book, I have discussed the concept of syntax sugar . As a recap, this is a term that describes variations to functions that Microsoft developers sometimes create to make DAX easier to learn and understand. The REMOVEFILTERS() function is an example of syntax sugar . When I first learnt DAX, I learnt that the ALL() function is the “remove filters” function. In fact, I still teach this concept to my students today. So as you may have guessed, the REMOVEFILTERS() function is actually just syntax sugar for the ALL() function that you can use when you want to remove filters in the way shown above. Personally I never use REMOVEFILTERS() because I just learnt to do it using ALL(), but of course you can use it if you like.
在本書中,我已經(jīng)多次討論了語法糖(syntax sugar)的概念?;仡欀暗慕忉?,這個術(shù)語其實(shí)是微軟開發(fā)人員有時為使DAX更容易學(xué)習(xí)和理解而創(chuàng)建的函數(shù)的變體(或者說是函數(shù)的一種簡便寫法)。REMOVEFILTERS()函數(shù)也可以理解為是語法糖的一個例子。Matt說他第一次學(xué)習(xí)DAX時,知道了ALL()函數(shù)是“清除篩選”的函數(shù),他在教學(xué)時也是這樣跟大家說的。其實(shí)我們可以把REMOVEFILTERS()函數(shù)當(dāng)成是ALL()函數(shù)的語法糖,當(dāng)你清除篩選時就可以使用REMOVEFILTERS()函數(shù)。使用REMOVEFILTERS()與否,看個人喜好。
語法:
REMOVEFILTERS([<table> | <column>[, <column>[, <column>[,…]]]])
? REMOVEFILTERS 只能用于清除篩選器,不能返回表。
? 在已計算的列或行級安全性 (RLS) 規(guī)則中使用時,不支持在 DirectQuery 模式下使用此函數(shù)。
三、ALLEXCEPT函數(shù) The ALLEXCEPT() Function
ALLEXCELPT函數(shù)和ALL函數(shù)可以說是師出同門,功能有相似,但也有不同。ALL函數(shù)是可以清除整個表的篩選,也可以清除一列或多列的篩選,當(dāng)你想清除一個表中很多列的篩選時,把這些列寫到ALL函數(shù)太麻煩了。這時我們就可以使用ALLEXCEPT函數(shù),把不需要清除篩選的列放到函數(shù)里就好了。我覺得可以用"非此既彼"來形容這個函數(shù)。
語法:
ALLEXCEPT(<table>,<column>[,<column>[,…]])?
ALLEXCEPT 函數(shù)的第一個參數(shù)必須是對基表的引用。 所有后續(xù)參數(shù)必須是對基列的引用。 不能將表表達(dá)式或列表達(dá)式用于 ALLEXCEPT 函數(shù)。
返回值
刪除了所有篩選器(針對指定列的篩選器除外)的一個表。
備注
此函數(shù)不單獨(dú)使用,而是用作中間函數(shù),可用于更改執(zhí)行過其他計算的結(jié)果集。
可以在不同的方案中使用 ALL 和 ALLEXCEPT:

四、ALLSELECTED函數(shù) The ALLSELECTED() Function
ALLSELECTED()函數(shù)的工作方式挺像ALL函數(shù)的,但是它們在其他視覺對象(例如切片器)和外部篩選區(qū)的工作方式不同。ALL會清除所有的篩選,不管你這個篩選在畫布的哪里放著。ALLSELECTED聽從外部篩選的(切片器、外部篩選區(qū)等),這一點(diǎn)在計算百分比時很有用。當(dāng)報表中有其它篩選(例如切片器、外部篩選區(qū)或從另一個可視化交叉篩選),并且您希望矩陣中的總百分比加起來是100%時,就可以使用ALLSELECTED函數(shù)。
接著使用本章前面的例子的矩陣,現(xiàn)在添加了一個[Group]切片器,[% of Global Sales]合計為38.7%;這是正確的,因?yàn)槠渌际S?1.3%的國家已經(jīng)使用[Group]切片器過濾掉了。
語法:
ALLSELECTED([<tableName> | <columnName>[, <columnName>[, <columnName>[,…]]]] )
返回值:不帶任何列和行篩選器的查詢的上下文。
備注:
? 如果有一個參數(shù),則該參數(shù)為 tableName 或 columnName。 如果有多個參數(shù),則它們必須是同一表中的列。
? 此函數(shù)與 ALL() 不同,因?yàn)樗A袅嗽诓樵冎酗@式設(shè)置的所有篩選器,并且保留了除行和列篩選器之外的所有上下文篩選器。
? 在已計算的列或行級安全性 (RLS) 規(guī)則中使用時,不支持在 DirectQuery 模式下使用此函數(shù)。
TOTAL SALES = SUM('Sales'[ExtendedAmount])?
TOTAL TERRITOY ALLSELECTED = CALCULATE([TOTAL SALES],ALLSELECTED(Territory))
% total allselected = DIVIDE([TOTAL SALES],[TOTAL TERRITOY ALLSELECTED])?

五、臨時度量值的用處 The Value of Interim Measures
把一個問題分成幾步來做,在實(shí)際工作中很有用。建議大家寫DAX時使用臨時度量值(我覺得也可以叫中間度量值),然后再創(chuàng)建需要的度量值,最終使用的度量值可以引用臨時度量值,這樣做更方便,中間步驟正確,也便于得到正確的結(jié)果,或者容易排隊(duì)錯誤,理解計算的中間步驟。這種方法和數(shù)學(xué)上的分步計算很相似。