理解 ALL, ALLEXCEPT, and ALLNOBLANKROW
ALL 都是一個(gè)有用的函數(shù),它返回一個(gè)表的所有行或一個(gè)列的所有值,這取決于您所使用的參數(shù)。例如,下面的DAX查詢返回產(chǎn)品表中的所有行
EVALUATE
ALL ( Product )
你不能在 ALL 參數(shù)中指定一個(gè)表表達(dá)式。您必須指定表名或列名列表。如果您使用單個(gè)列,那么結(jié)果就是一張?jiān)砣ブ睾笮纬傻奈ㄒ恢盗斜恚鐖D3-8所示。
EVALUATE
ALL ( Product[Class] )

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

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

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

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

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

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

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

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