理解 ALL, ALLEXCEPT, and ALLNOBLANKROW
ALL 都是一個有用的函數(shù),它返回一個表的所有行或一個列的所有值,這取決于您所使用的參數(shù)。例如,下面的DAX查詢返回產(chǎn)品表中的所有行
EVALUATE
ALL ( Product )
你不能在 ALL 參數(shù)中指定一個表表達式。您必須指定表名或列名列表。如果您使用單個列,那么結(jié)果就是一張原表去重后形成的唯一值列表,如圖3-8所示。
EVALUATE
ALL ( Product[Class] )

你可以在 ALL函數(shù)的參數(shù)中指定來自同一個表的更多列。如果您使用許多列,那么結(jié)果將是一張包含了這些列中已有的值組合的列表(可以理解為對多個列做笛卡爾積,然后篩選其中原表中已經(jīng)存在的列組合)。例如,下面的表達式產(chǎn)生如圖3-9所示的結(jié)果:
EVALUATE
ALL ( Product[Class], Product[Color] )
ORDER BY Product[Color]

在所有的變體中,ALL函數(shù)忽略了任何現(xiàn)有的過濾器來產(chǎn)生它的結(jié)果。您可以將ALL函數(shù)用作迭代函數(shù)的參數(shù),例如SUMX和FILTER,或者作為CALCULATE函數(shù)中的篩選參數(shù)(稍后您將看到)
如果您想要在一個ALL函數(shù)調(diào)用中包含表格的大部分列,您可以使用ALLEXCEPT函數(shù)來代替。ALLEXCEPT函數(shù)的語法需要一個表,后面是您想要從結(jié)果中排除的列。因此,在表格的其他列中,ALLEXCEPT返回一張表,其中包含了其他列現(xiàn)有的值組合的唯一列表。
在實際運用中,這是一種編寫DAX表達式的方法,它將自動包含非參數(shù)列的所有結(jié)果,以及在之后的表模型中可能出現(xiàn)的任何額外的列。例如,如果您有一個包含5個列(ProductKey, Product Name, Brand, Class, Color)的產(chǎn)品表,那么下面的語法就會產(chǎn)生相同的結(jié)果
ALL ( Product[Product Name], Product[Brand], Product[Class] )
ALLEXCEPT ( Product, Product[ProductKey], Product[Color] )
但是,如果您稍后添加兩列 Product[Unit Cost]和Product[Unit Price],那么ALL函數(shù)的結(jié)果會忽略它們,而ALLEXCEPT函數(shù)則將返回等效的:
ALL (
Product[Product Name],
Product[Brand],
Product[Class],
Product[Unit Cost],
Product[Unit Price]
)
下列查詢返回一個表,該表除了產(chǎn)品表之外的Product Code和Color以外的所有列。圖3-10的結(jié)果與原始表的行數(shù)相同,因為結(jié)果包括ProductKey列,它每一行具有惟一的值。結(jié)果中的其他列組合可能會返回較少的行數(shù),因為ALLEXCEPT消除了返回列中值的重復(fù)組合。
EVALUATE
ALLEXCEPT ( Product, Product[ProductKey], Product[Color] )

在前面的例子中,您已經(jīng)在一個EVALUATE語句中看到了ALL函數(shù),它執(zhí)行DAX表達式,而沒有任何現(xiàn)有的篩選條件。出于這個原因,最好是看一個在透視表中使用ALL函數(shù)計算表的行數(shù)的例子,這些例子中每個單元格使用不同的篩選條件來計算度量值。考慮以下度量值:
[Products] := COUNTROWS ( Product )
[All Products] := COUNTROWS ( ALL ( Product ) )
[All Brands] := COUNTROWS ( ALL ( Product[Brand] ) )
您可以在圖3-11中看到每個度量值的不同結(jié)果的示例

對于每一個產(chǎn)品類別,在All Products和All Colors列中,總是有相同的結(jié)果。在ALL函數(shù)的計算中忽略了透視表中單元格的篩選條件。
當(dāng)你調(diào)用ALL函數(shù)在一個關(guān)系的父表時,如果子表包含一個或多個行在父表中不匹配任何值的行,就會返回一個額外的空白行。您可以通過使用 ALLNOBLANKROW 函數(shù) 代替ALL函數(shù)來忽略這個特殊的行。
考慮下面的度量值:
[All Products] := COUNTROWS ( ALL ( Product ) )
[All NoBlank Products] := COUNTROWS ( ALLNOBLANKROW ( Product ) )
[All Brands] := COUNTROWS ( ALL ( Product[Brand] ) )
[All NoBlank Brands] := COUNTROWS ( ALLNOBLANKROW ( Product[Brand] ) )
[All Sizes] := COUNTROWS ( ALL ( Product[Size] ) )
[All NoBlank Sizes] := COUNTROWS ( ALLNOBLANKROW ( Product[Size] ) )
在圖3-12中,您可以看到ALL和ALLNOBLANKROW度量值之間的區(qū)別。對于Product表 和 the Products[Model]列,ALL版本的度量值比ALLNOBLANKROW版本多返回一行。原因是銷售表中有一些行,在產(chǎn)品表中沒有與之匹配的行,因此額外的一行實際上被添加到產(chǎn)品表中,您可以在圖3-12中看到(空白)行中的結(jié)果。

您應(yīng)該注意到, All Sizes和All NoBlank Sizes計算結(jié)果總是相同。這些度量查詢Products[Size]列的數(shù)量。在這種情況下,ALL和ALLNOBLANKROW函數(shù)返回相同的值,因為 Products[Size]列已經(jīng)包含了一個產(chǎn)品的空白值。在圖3-13的例子中,有569個空白大小的產(chǎn)品,加上一個額外的無法引用銷售表產(chǎn)品空白產(chǎn)品,總共有570個。對于Products[Size]列,所有這些行都被分組在同一個的(空白)值中。

只有當(dāng)你寫了一個DAX公式需要它忽略了關(guān)系中不匹配的值時,你才應(yīng)該使用ALLNOBLANKROW。然而,相較于ALL函數(shù),ALL的使用則顯得更為通用,而ALLNOBLANKROW用的則很少。
理解 VALUES和 DISTINCT
在上一節(jié)中,您已經(jīng)看到,ALL主要用于返回一個列中所有惟一值的表。DAX提供了另外兩個類似的函數(shù),它們返回一個列的惟一值列表:VALUES和DISTINCT
如果在沒有任何其他篩選條件情況下,在EVALUATE語句中 VALUES和 DISTINCT似乎是相同的。然而,當(dāng)你把這些函數(shù)放在DAX度量值中時,你可以觀察到一個不同的行為,因為計算發(fā)生在一個透視表的每個單元格的不同上下文中??紤]以下在產(chǎn)品表中Brand列和 Size 列計算不同唯一值數(shù)量的度量值。
[Products] := COUNTROWS ( Product )
[Values Brands] := COUNTROWS ( VALUES ( Product[Brand] ) )
[Distinct Brands] := COUNTROWS ( DISTINCT ( Product[Brand] ) )
[Values Sizes] := COUNTROWS ( VALUES ( Product[Size] ) )
[Distinct Sizes] := COUNTROWS ( DISTINCT ( Product[Size] ) )
VALUES 返回當(dāng)前可見單元中惟一值列表,包括沒有匹配的空白行。 DISTINCT同樣,但是不返回沒有匹配的空白行。但是,如果一個空白值作為列的有效值出現(xiàn),那么這兩個函數(shù)都將包含一個空行。唯一的區(qū)別是添加了空白行來處理關(guān)系中缺失值
一個例子可能會幫助你區(qū)分這種不同。正如表3-14,每個產(chǎn)品等級篩選出不同數(shù)量的產(chǎn)品。比如Deluxe有360種產(chǎn)品,有11個不同的品牌和204個不同的尺碼。 VALUES 和 DISTINCT 返回相同的結(jié)果,只有一個例外:透視表中行的(空白)產(chǎn)品類。結(jié)果增加了一個虛擬行,以顯示在Sales Amount中沒有匹配到的產(chǎn)品。

另一個在圖3-14中可見的區(qū)別在 Grand Total中。 VALUES 應(yīng)用于 Product[Brand],返回的值比應(yīng)用在同樣列上DISTINCT的值多一個。然而,這并不會發(fā)生在 VALUES 應(yīng)用于Products[Size]的值上,后者返回的值與 DISTINCT應(yīng)用在同樣的列上相同。這個原因是 Distinct Sizes 列包含至少一個產(chǎn)品的空白值,因此添加的空白產(chǎn)品不會為 Distinct Sizes 列添加一個新的惟一值。
當(dāng)沒有篩選條件時, DISTINCT行為與ALLNOBLANKROW的行為相同,與此對比,VALUES行為與ALL行為相同。
VALUES也接受一張表作為參數(shù)。在這種情況下,它返回在當(dāng)前可見的整個表,同時也包括沒有匹配的空白行。例如,在數(shù)據(jù)模型中考慮以下度量值,其中Sales表與 Product 表有關(guān)系,并包含與產(chǎn)品主鍵不匹配的交易。
[Products] := COUNTROWS ( Product )
[Values Products] := COUNTROWS ( VALUES ( Product ) )
[All NoBlank Products] := COUNTROWS ( ALLNOBLANKROW ( Product ) )
[All Products] := COUNTROWS ( ALL ( Product ) )
VALUES作為標(biāo)量值使用
即使 VALUES 是一個表函數(shù),您也經(jīng)常使用它來計算標(biāo)量值,因為在DAX中有一個特殊的特性,您將在本節(jié)中學(xué)習(xí)。例如,您可以在表達式中找到VALUES,比如下面的表達式,它會顯示顏色名稱,以確保某一特定選擇的產(chǎn)品都具有相同的顏色:
[Color Name] :=
IF ( COUNTROWS ( VALUES ( Product[Color] ) ) = 1, VALUES ( Product[Color] ) )
您可以在圖3-15中看到結(jié)果。當(dāng)Color Name列包含空白時,這意味著有兩種或更多不同的顏色

這里的有趣之處在于,我們將VALUES的結(jié)果作為標(biāo)量值,即使它返回一個表。這不是一種VALUES特殊的行為而是DAX語言一種更普遍的行為。
如果一個表表達式返回一個帶有一行和一列的表,那么如果需要的話,可以自動轉(zhuǎn)換成為標(biāo)量值。
在實踐中,如果結(jié)果恰好有一行和一列,您可能會使用任何表表達式作為標(biāo)量值。當(dāng)表格返回更多的行時,您會在執(zhí)行時得到這個錯誤:“在期望單個值的地方提供了多個值的表。“出于這個原因,您應(yīng)該始終編寫一個返回不同結(jié)果的條件來確保能夠轉(zhuǎn)換為標(biāo)量值,以防表表達式返回更多的行(您應(yīng)該已經(jīng)知道,當(dāng)您編寫DAX表達式時,表表達式是否只返回一行)。
前面例子的 Color Name度量使用COUNTROWS來檢查產(chǎn)品表的 Color 列是否只有一個值。一種更簡單的方法是使用HASONEVALUE,它執(zhí)行相同的檢查,如果列只有一個值返回的值,反之則返回 FALSE 。以下兩個語法是等價的
COUNTROWS ( VALUES ( <column> ) ) = 1
HASONEVALUE ( <column> )
您應(yīng)該使用HASONEVALUE而不是COUNTROWS,原因有兩個:它更易于閱讀,而且可能會稍微快一些。下面是基于HASONEVALUE的 Color Name 度量值的更好的實現(xiàn):
[Color Name] :=
IF ( HASONEVALUE ( Product[Color] ), VALUES ( Product[Color] ) )
您經(jīng)常使用 VALUES 作為標(biāo)量表達式的原因是它返回單個列,并且可能返回單行,這取決于執(zhí)行上下文。在許多DAX模式中, VALUES 作為標(biāo)量表達式是很常見的,并且在本書中反復(fù)出現(xiàn)。