《DAX權威指南》簡體版 (第三章)02
了解ALL缘挽,ALLEXCEPT和ALLNOBLANKROW
ALL系列函數(shù)包括ALL裕膀、ALLEXCEPT以及?ALLNOBLANKROW员串。
? ? ? ? ?所有這些都是一個有用的系列函數(shù):
它返回一個表的所有行或者一個列的所有值,這取決于使用的參數(shù)昼扛。
例如寸齐,下面的DAX查詢返回產(chǎn)品表中的所有行:
EVALUATE
ALL?( Product )
不能在ALL( )參數(shù)中指定一個表表達式,而必須指定一個表名的列表或列名的列表抄谐。如果使用單個列渺鹦,結果是一個包含唯一值的列表,如圖3-8所示蛹含。
EVALUATE
ALL?( Product[Class] )?--ALL
參數(shù)為一個表的列表
譯者:Class列表中可能存在一個或多個列值為Econmy、Regular浦箱、Deluxe的行吸耿,ALL(Class)的結果是該列的所有唯一值的列表,即只有Econmy酷窥、Regular咽安、Deluxe三個值的列表。
可以在ALL函數(shù)的參數(shù)中指定來自同一個表的更多個列蓬推。如果使用多個列作為參數(shù)妆棒,結果將是一個具有相同行數(shù)量的列表,其中包含這些列中現(xiàn)有值的組合列表。例如糕珊,下面的表達式生成圖3-9所示的結果蛋铆。
EVALUATE
ALL?( Product[Class],Product[Color] )?
?ORDER BY Product[Color]
? ? ? ?譯者補充:如上圖刺啦,[Class]列與[Color]列雖然有重復的非唯一值,例如[Class]列的行值Economy,[Color]列的行值Silver Grey纠脾、White玛瘸。從單列的結果來看,似乎是不對的苟蹈。
? ? ? 但是糊渊,ALL?( Product[Class],Product[Color] )是針對[Class]和[Color]兩列取唯一值慧脱,其中包含這兩列中現(xiàn)有值的組合列表中的唯一值渺绒。為方便觀察,我們換個角度看看:
? ? ? ?如圖菱鸥,[Class]和[Color]列的對應行值的兩兩組合的值宗兼,例如:Economy+Silver是一個唯一值,依次類推氮采,Economy+Silver Grey也是唯一值……殷绍。由于在實際的運用中,ALL()的列表結果很重要鹊漠,所以加了這點補充主到。
? ? ? ?有的人將ALL(多個列)的結果理解為:先對多個列做笛卡爾積,然后篩選其中原表中已經(jīng)存在的列值組合躯概。這種說法對不對登钥?并沒有答案,關鍵是DAX內(nèi)部引擎的工作原理是不能用猜想或一兩個正確的公式就可以證明的娶靡。
在ALL的變體函數(shù)中牧牢,都忽略了任何現(xiàn)有的篩選器來產(chǎn)生結果。
我們可以將這些ALL系列函數(shù)作為迭代函數(shù)的參數(shù)(如SUMX和FILTER)固蛾,或者作為一個CALCULATE函數(shù)中的篩選器參數(shù)(稍后將會看到)结执。
如果想利用ALL函數(shù)調用某個表的大部分列度陆,則可以使用ALLEXCEPT代替艾凯。要想從結果中排除哪些列,則需要一個表懂傀,后面再是該表中無須排除的列趾诗。
因此,?ALLEXCEPT返回一個表,即該函數(shù)指定列表之外的其他列恃泪,其中包括這些其他列表的唯一值組合的列表郑兴。
實際上,ALLEXCEPT是一種編寫DAX表達式的方法贝乎,它將自動包含在ALL非參數(shù)列的所有結果情连,以及之后數(shù)據(jù)模型中可能新增的新的任何額外的列。
例如览效,如果有一個帶有五個列的產(chǎn)品表(ProductKey却舀,?Product Name,?Brand锤灿,?Class挽拔,?Color--產(chǎn)品代碼、產(chǎn)品名稱但校、品牌螃诅、類別、顏色)状囱,下面的語法產(chǎn)生相同的結果:
ALL?( Product[Product Name]术裸,Product[Brand],Product[Class] )?//?除去的三列(ALL包含的三個列)
ALLEXCEPT?( Product亭枷,?Product[ProductKey]穗椅,?Product[Color] )?//?保留的兩列(相當于ALL包含的除去這兩列之外的任何其他列)
然而,如果以后再再該表中添加兩列?:[Unit Cost]和?[Unit Price]--產(chǎn)品單位成本和產(chǎn)品(單價)奶栖,那么匹表,ALL()的結果將忽略它們,與前面ALLEXCEPT的返回結果等效宣鄙。
下面的查詢返回一個表袍镀,該表除了[Code]和[Color]--產(chǎn)品代碼和產(chǎn)品顏色列之外的所有列。
ALL?(Product[Product Name]冻晤,Product[Brand]苇羡,Product[Class],
Product[Unit Cost]鼻弧,Product[Unit Price])?–-不包含[Code]和[Color]兩列设江,其結果等效于下面的公式:
EVALUATE
ALLEXCEPT?( Product,
Product[ProductKey]攘轩,Product[Color] )
后者的好處是叉存,不受表中新增列表的影響。
圖3-10是上述公式的結果度帮。該結果與原表的行數(shù)相同歼捏,因為結果包含了ProductKey列声畏,該列的每一行都是一個唯一值渔伯。結果為ALLEXCEPT參數(shù)指定列之外的其他列的組合,但可能會返回更少的行,因為返回的列值中刪除了重復值甘邀。
前面的例子季眷,是一個ALL函數(shù)的EVALUATE輸出語句,它執(zhí)行一個DAX表達式腺晾,而沒有任何現(xiàn)有的篩選條件瓢棒。也就是說:
ALL的計算語句,它在沒有任何現(xiàn)有篩選器的情況下執(zhí)行DAX表達式丘喻。
出于這個原因脯宿,我們最好是看一個在透視表中使用ALL函數(shù)計算表的行數(shù)的例子,其中使用不同的篩選器對每個度量的單元格值進行計算泉粉。
考慮以下度量:
[Products]?:????=?COUNTROWS?( Product )
[All Products] :=?COUNTROWS?(?ALL?( Product )?)
[All Brands] :?=?COUNTROWS?(?ALL?(?Product[Brand]?)?)
可以在圖3-11中看到每個度量的不同結果的示例连霉。
對于每個產(chǎn)品類別(第一列中的每行)跺撼,在[All Products]和[All Blands]列中都產(chǎn)生相同的數(shù)字,是因為度量公式中ALL()語句的計算忽略了透視表的每個單元格定義的篩選器讨彼。
譯者:(1)[All Products]?:=?COUNTROWS?(?ALL?( Product )?)度量歉井,僅計算All?(Product)的結果:即Product表的全部唯一值行的計數(shù)(結果為2517)。
? ? ? ?(2)[All Brands]?:=?COUNTROWS?(?ALL?( Product[Brand] )?)度量哈误,僅計算ALL?( Product[Brand] )的結果:即Product表的[Brand]列的唯一值行的計數(shù)(結果為12哩至,[Brand]列表中唯一值為12個)。
當調用關系的父表時蜜自,如果子表包含一個或多個與父表中的值不匹配的行菩貌,則會檢索額外的空行≈剀可以使用ALLNOBLANKROW而不是ALL的方法來忽略結果中的這個特殊行箭阶。考慮以下度量:
[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ū)別仇参。這些度量的值中,?ALL版本度量結果與對應的ALLNOBLANKROW版本度量結果都多一個婆殿。原因是Sales表中有一些行在Product表中并沒有匹配的行诈乒,因此,實際上添加了一個額外的行鸣皂,你可以在圖3-12中看到(空白)行中的結果抓谴。
你應該注意到暮蹂,?[All Sizes ]和?[All NoBlank Sizes]度量總是返回相同的值(622)寞缝,該度量查詢Products[Size]列的數(shù)量癌压。因為Products[Size]列已經(jīng)包含了一個空白值的產(chǎn)品,所以這種情況下ALL?和?ALLNOBLANKROW函數(shù)返回相同的值荆陆。
在圖3-13的示例中滩届,有569個(blank)--空白計數(shù)的產(chǎn)品,加上額外的被啼,其中包含對銷售表中不匹配的產(chǎn)品的引用的一個空白產(chǎn)品帜消,總共570個。所有這些行被分組在Products[Size]列的?(空白)值中用于計算浓体。
當你需要編寫一個遍歷表命浴,然后忽略關系中不匹配的值時娄猫,應該使用ALLNOBLANKROW。然而生闲,通用都是使用ALL媳溺,而ALLNOBLANKROW卻很少被使用。
了解VALUES?和?DISTINCT
在前一節(jié)中碍讯,已經(jīng)看到悬蔽,?ALL(一個列表)結果返回該列所有唯一值行值的表。DAX函數(shù)提供了另外兩個類似的函數(shù):VALUES?和?DISTINCT捉兴,也返回一個列表的唯一值的列蝎困。
在沒有任何其他篩選操作的情況下,如果在EVALUATE語句中使用VALUES?和?DISTINCT看起來是相同的倍啥。
但是难衰,當將這兩個函數(shù)分別放置在DAX度量中時,就可以觀察到它們不同的行為逗栽。因為在一個數(shù)據(jù)透視表的每個單元格中盖袭,計算發(fā)生在當前不同的篩選子集中。
考慮下面的度量彼宠,計算Product[Brand]和Product[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()返回當前單元格中可見的唯一值列表,包括未匹配值的可選空白行凭峡。DISTINCT執(zhí)行相同的操作拙已,但不返回未匹配值的空白(這是兩者的區(qū)別)。
然而摧冀, 如果空白值本身為某個列的有效值倍踪,那么系宫,這兩個函數(shù)都包含空白行。唯一的區(qū)別是建车,是否需要添加空白行來處理關系中的缺失值扩借。一個例子可能有助于說明這一差異。
如圖3- 14所示缤至,每個產(chǎn)品類別都篩選到不同數(shù)量的產(chǎn)品潮罪。例如,Deluxe?有360個產(chǎn)品领斥、11個獨特的brands--品牌嫉到、204個獨特的sizes--尺寸。這時月洛,VALUES?和?DISTINCT返回這些相同的結果何恶。只有一個例外:在數(shù)據(jù)透視表之中的產(chǎn)品類別行的(blank)—(空白),其結果實際上包括增加的一行嚼黔,以顯示不匹配產(chǎn)品的銷售金額的值细层。
在圖3-14中,另一個差異是可見的爵卒。VALUES()?應用于Product[Brand]列返回的值比DISTINCT()應用于同一列的值要多虚缎。
但是,這不會發(fā)生在DISTINCT()應用到Product[Brand]列的值上钓株,它返回的值與對應列上的值相同实牡。因為DISTINCT()的Products[Size]列包含至少一個產(chǎn)品的空白值,因此添加的空白產(chǎn)品不會為[Distinct Sizes]列添加一個新的唯一值轴合。
當沒有篩選器時创坞,DISTINCT()的行為對應于ALLNOBLANKROW(),而VALUES()的行為對應于ALL()受葛。
比較特殊的是题涨,VALUES()也接受一個表作為參數(shù)。在這種情況下总滩,它將返回當前單元格中可見的整個表纲堵,并有選擇地包括未匹配關系的空行。
例如闰渔,在數(shù)據(jù)模型中考慮以下度量席函,其中Sales表與Product產(chǎn)品表具有關系,并包含與產(chǎn)品鍵不匹配的任何現(xiàn)有產(chǎn)品的事務記錄冈涧。
[Products]?:=?COUNTROWS?( Product )
[Values Products]?:=?COUNTROWS?(?VALUES?( Product ) )
[All NoBlank Products]?:=?COUNTROWS?(?ALLNOBLANKROW( Product))
[All Products]?:=?COUNTROWS?(?ALL?( Product ) )?
可以在圖3-15中看到茂附,在這種情況下正蛙,當沒有篩選器時,VALUES的結果對應于ALL的行為营曼,包括添加的空白行乒验,以顯示未匹配產(chǎn)品的銷售額。在這種情況下溶推,不能在一個表上使用DISTINCT徊件。
如果需要刪除一列中重復的行奸攻,?DAX函數(shù)中沒有單獨這樣的函數(shù)來刪除重復的行(這時必須使用SUMMARIZE()蒜危,稍后將在第9章看到)。
然而睹耐, 當沒有篩選器時辐赞,[Products]度量計算表中的行數(shù),并忽略一個可能的空白行硝训,該行為與ALLNOBLANKROW()相同响委。
圖3-15的值,并考慮在產(chǎn)品表中添加空白行以獲得不匹配的銷售值窖梁。
譯者:在學習完列表關系后赘风,ALL()行為與VALUES()行為是有區(qū)別的:ALL()行為在于創(chuàng)建一個去掉關系的唯一值列表(不能用于篩選等),VALUES()的唯一值結果列表間保持原列表關系纵刘。
使用VALUES創(chuàng)建標量值
即使VALUES是一個表函數(shù)邀窃,也會經(jīng)常使用它來計算標量值。在這一節(jié)中將學習到DAX的一個特殊特性假哎。例如瞬捕,可以在表達式中設置VALUES(),如下面的一個DAX--[ColorName]度量舵抹,用于顯示顏色名稱肪虎,以確保選擇的為相同顏色的所有產(chǎn)品
[Color Name]?:=?IF?(COUNTROWS?(
? ? ? ? ? ? ? ? ? ? VALUES?( Product[Color] ) ) =?1,VALUES?( Product[Color] ))??
譯者:這是使用IF()測試一列中布爾值(真/假條件)的第一種方法惧蛹。實際業(yè)務場景中經(jīng)常用到扇救,后面將有更優(yōu)化的方法介紹。
可以在圖3-16中看到結果香嗓。當[ColorName]度量結果包含空白時迅腔,意味著有兩個或更多不同的顏色。
有趣的一點是饱岸,我們使用VALUES()作為標量值的結果掺出,即使它返回一個表徽千。這不是VALUES的特殊行為,但它代表DAX語言更一般的行為:
如果需要一個表表達式返回一行或一列汤锨,并需要它自動完成双抽,則可以使用任何表表達式來將列表轉換為標量值(即將列表轉換為值列表)。
實踐中闲礼,如果結果正好為一行或一列牍汹,可以使用任何表表達式作為一個標量值。而當表返回多行時柬泽,在執(zhí)行時會出現(xiàn)這樣一個錯誤:“一個多值的表是由其他方式提供的慎菲。”
因此锨并,你應該保持該標量值的轉換條件露该,使表表達式返回一個不同的多行結果?(你應該已經(jīng)知道,當你寫DAX公式時第煮,該表表達式只返回一行)解幼。前面的[Color Name]度量示例,使用COUNTROWS?(?VALUES?( Product[Color] ) ) =?1:即COUNTROWS()檢查Color--顏色列在Products--產(chǎn)品表里的選擇是一個值包警。
一個更簡單的完全相同的控制方法是使用HASONEVALUE撵摆,它執(zhí)行同樣的檢查,如果列只有一個值害晦,返回TRUE特铝,否則返回FALSE。以下兩個語法是等價的:
COUNTROWS?(?VALUES?( ) ) =?1,HASONEVALUE?( )
你應該用HASONEVALUE代替COUNTROWS篱瞎,這有兩個原因:可讀性更強苟呐,以及可以稍快一些。下面是一個更好的基于HASONEVALUE設置的度量:
[Color Name]俐筋。
[Color Name]?:= IF (HASONEVALUE ( Product[Color] )牵素,?VALUES ( Product[Color] ))??
?經(jīng)常使用值作為標量表達式的原因是:在不同的篩選條件下,它返回單個列澄者,或者返回單個行笆呆。在許多DAX模式中,使用VALUES()作為標量表達式是很常見的粱挡,并且在本書中反復出現(xiàn)赠幕。