在本章中启绰,您將學(xué)習(xí)DAX中標(biāo)量函數(shù)和表函數(shù)之間的區(qū)別满粗。表函數(shù)對(duì)于DAX中的內(nèi)部計(jì)算非常重要爱谁,當(dāng)您為度量值或計(jì)算列編寫DAX查詢而不是DAX表達(dá)式時(shí)晒喷,表函數(shù)非常有用。
本章的目標(biāo)是介紹表函數(shù)的概念访敌,而不是對(duì)您第一次在這里看到的所有函數(shù)提供詳細(xì)的解釋凉敲。第9章“高級(jí)表函數(shù)”對(duì)表函數(shù)進(jìn)行更深入分析。這里寺旺,我們將解釋表函數(shù)在DAX中的作用爷抓,以及如何在常見場(chǎng)景中使用它們,包括在標(biāo)量DAX表達(dá)式中阻塑。
3.1 介紹表函數(shù)
DAX是一種函數(shù)式語(yǔ)言蓝撇,您可以在其中編寫表達(dá)式,在計(jì)算后生成結(jié)果叮姑。到目前為止唉地,您已經(jīng)看到DAX表達(dá)式通常返回單個(gè)值据悔,例如字符串或數(shù)字。我們將這些表達(dá)式稱為標(biāo)量表達(dá)式耘沼。定義度量值或計(jì)算列時(shí)极颓,你總是編寫標(biāo)量表達(dá)式,如下所示:
= 4 + 3
= "DAX is a beautiful language"
= SUM ( Sales[Quantity] )
但是群嗤,您可以編寫一個(gè)DAX表達(dá)式來生成一個(gè)表菠隆。您不能將表表達(dá)式直接分配給度量值或計(jì)算列,但表表達(dá)式是DAX的重要組成部分狂秘。例如骇径,有DAX函數(shù)接收表表達(dá)式作為參數(shù),并且需要表表達(dá)式來編寫DAX查詢者春。
表表達(dá)式的最簡(jiǎn)單示例是在DAX表達(dá)式中引用表名破衔,例如以下表達(dá)式返回Sales表的整個(gè)內(nèi)容(所有列和所有行):
= Sales
但是,如果您試圖將上一個(gè)表達(dá)式分配給度量值或計(jì)算列钱烟,則會(huì)出現(xiàn)錯(cuò)誤晰筛,因?yàn)槎攘恐敌枰獦?biāo)量值作為結(jié)果。您需要操作表表達(dá)式以獲取標(biāo)量值拴袭。這可以通過使用接受表表達(dá)式作為參數(shù)的函數(shù)來實(shí)現(xiàn)读第。例如,使用COUNTROWS計(jì)算表中包含的行數(shù):
= COUNTROWS ( Sales )
COUNTROWS函數(shù)具有以下定義:
COUNTROWS ( <table> )
當(dāng)一個(gè)DAX函數(shù)接受表表達(dá)式作為參數(shù)時(shí)拥刻,您可以在該參數(shù)中寫入表的名稱怜瞒,或者您可以編寫一個(gè)返回表的函數(shù)。
我們根據(jù)DAX函數(shù)的返回類型對(duì)其進(jìn)行分類般哼。我們稱返回標(biāo)量值的函數(shù)為“標(biāo)量函數(shù)”吴汪,稱返回表的函數(shù)為“表函數(shù)”。例如逝她,COUNTROWS是一個(gè)標(biāo)量函數(shù)浇坐,因?yàn)樗邮芤粋€(gè)表作為參數(shù),并返回一個(gè)數(shù)字黔宛。
許多表函數(shù)通常操作表近刘,更改原始表的行或列。例如臀晃,您可以使用以下表達(dá)式觉渴,計(jì)算Sales表中價(jià)格大于100的行數(shù):
= COUNTROWS (
FILTER (
Sales,
Sales[Unit Price] > 100
))
在上一個(gè)表達(dá)式中,F(xiàn)ILTER返回一個(gè)僅包含Sales中單位價(jià)格大于100的行的表徽惋。在本章后面案淋,您將了解有關(guān)FILTER函數(shù)的更多信息。
通常险绘,您在代碼中使用表表達(dá)式來迭代表的行并聚合一些值踢京,以返回標(biāo)量值作為結(jié)果誉碴。您不能將表表達(dá)式直接分配給度量值和計(jì)算列。但是瓣距,您可以在計(jì)算表中使用表表達(dá)式(如果此功能將來可用)或在DAX查詢中使用表表達(dá)式黔帕,從而得到表達(dá)式的內(nèi)容。
例如蹈丸,您可以通過執(zhí)行以下表表達(dá)式來獲取Sales中單位價(jià)格大于100的行的表成黄,您可以在圖3-1中看到返回的內(nèi)容。
= FILTER (
Sales,
Sales[Unit Price] > 100
)
DAX還為您提供了EVALUATE語(yǔ)句奋岁,您可以使用它來計(jì)算表表達(dá)式:
EVALUATE
FILTER (
Sales,
Sales[Unit Price] > 100
)
您可以在可以執(zhí)行DAX查詢的任何客戶端工具(Microsoft Excel,DAX Studio荸百,SQL Server Management Studio闻伶,Reporting Services等)中執(zhí)行上面的DAX查詢。在下一節(jié)中够话,您將看到EVALUATE語(yǔ)法的詳細(xì)說明虾攻。
3.2 EVALUATE 語(yǔ)法
您可以將DAX用作編程語(yǔ)言和查詢語(yǔ)言。
DAX查詢是一個(gè)返回表的DAX表達(dá)式更鲁,與EVALUATE語(yǔ)句一起使用。完整的DAX查詢語(yǔ)法如下:
[DEFINE { MEASURE <tableName>[<name>] = <expression> }]
EVALUATE <table>
[ORDER BY {<expression> [{ASC | DESC}]} [, ...]
[START AT {<value>|<parameter>} [, ...]] ]
初始DEFINE MEASURE部分可以用于定義查詢的本地度量(即奇钞,它們存在于查詢周期中)澡为。當(dāng)您調(diào)試公式時(shí),它變得非常有用景埃,因?yàn)槟梢远x一個(gè)本地度量媒至,對(duì)它進(jìn)行測(cè)試,然后在它的行為符合預(yù)期時(shí)將其放入模型中谷徙。您將在第9章中看到此語(yǔ)法的更多示例拒啰。
大多數(shù)語(yǔ)法都是由可選參數(shù)組成的。最簡(jiǎn)單的查詢是從現(xiàn)有表中檢索所有列和行:
EVALUATE Product
您可以在圖3-2中看到結(jié)果完慧。
要控制排序順序,可以使用ORDER BY子句:
EVALUATE Product
ORDER BY
Product[Color],
Product[Brand] ASC,
Product[Class] DESC
備注:
請(qǐng)注意屈尼,模型中定義的“按列排序”屬性在DAX查詢中不起作用册着。即使您可能通過根據(jù)Sort By Column屬性查詢單個(gè)列而看到排序數(shù)據(jù),您也不必依賴此行為脾歧,就像您不能依賴SQL查詢中的聚簇索引一樣甲捏。生成動(dòng)態(tài)DAX查詢的客戶端應(yīng)讀取模型元數(shù)據(jù)中的“按列排序”屬性,然后生成相應(yīng)的ORDER BY條件鞭执。在DAX和SQL中司顿,必須始終使用顯式ORDER BY條件來獲取排序數(shù)據(jù)芒粹。
ASC和DESC關(guān)鍵字是可選的;如果不填大溜,則默認(rèn)使用ASC化漆。您可以在圖3-3中看到上一個(gè)查詢的結(jié)果,其中數(shù)據(jù)按顏色猎提、品牌和類排序获三。
START AT條件也是可選的疙教,并且只能與ORDER BY子句一起使用。您可以在ORDER BY語(yǔ)句中為每列指定起始值伞租。 START AT條件對(duì)于無狀態(tài)應(yīng)用程序中的分頁(yè)非常有用贞谓,該應(yīng)用程序僅從查詢中獲取有限數(shù)量的行,然后在用戶請(qǐng)求下一頁(yè)數(shù)據(jù)時(shí)發(fā)送另一個(gè)查詢葵诈。例如裸弦,查看以下查詢:
EVALUATE Product
ORDER BY
Product[Color],
Product[Brand] ASC,
Product[Class] DESC
START AT
"Yellow", "Tailspin Toys"
查詢返回圖3-4中所示的表,其中僅包含從Yellow作喘,Tailspin Toys開始的行理疙。
請(qǐng)注意,“starting from”的概念取決于ORDER BY子句中指定的順序方向贰锁。如果您為Product[Brand]指定DESC赃梧,如以下示例所示,結(jié)果中不包括Wide World Importers豌熄,其他品牌(如Southridge Video和 Northwind Traders)跟著Tailspin Toys授嘀。您可以在圖3-5中看到以下查詢的結(jié)果。
EVALUATE Product
ORDER BY
Product[Color],
Product[Brand] DESC,
Product[Class] DESC
START AT
"Yellow", "Tailspin Toys"
要篩選DAX查詢返回的行并更改列夯接,必須使用特定的表函數(shù)在EVALUATE關(guān)鍵字之后操作表表達(dá)式。本章介紹了一些表表達(dá)式纷妆,而第9章介紹了其他表表達(dá)式盔几。
3.3 使用表表達(dá)式
正如您在本章開頭所看到的,您經(jīng)常使用表表達(dá)式作為其他DAX函數(shù)的參數(shù)掩幢。典型的用法是在迭代表的函數(shù)中逊拍,為每一行計(jì)算DAX表達(dá)式上鞠。比如所有以“X”結(jié)尾的聚合函數(shù),例如SUMX:
[Sales Amount] :=
SUMX (
Sales,
Sales[Quantity] * Sales[Unit Price]
)
您可以使用表函數(shù)替換簡(jiǎn)單的Sales表引用芯丧。例如芍阎,您可以使用FILTER函數(shù)僅考慮數(shù)量大于1的Sales:
[Sales Amount Multiple Items] :=
SUMX (
FILTER (
Sales,
Sales[Quantity] > 1
),
Sales[Quantity] * Sales[Unit Price]
)
在計(jì)算列中,還可以使用RELATEDTABLE函數(shù)檢索一對(duì)多關(guān)系的多端表的所有行缨恒。例如谴咸,Product表中的以下計(jì)算列計(jì)算相應(yīng)產(chǎn)品的銷售額:
Product[Product Sales Amount] =
SUMX (
RELATEDTABLE ( Sales ),
Sales[Quantity] * Sales[Unit Price]
)
您可以在第4章“理解計(jì)算上下文”中的“行上下文和關(guān)系”這一節(jié)中找到RELATEDTABLE表函數(shù)的詳細(xì)說明
您可以在同一DAX表達(dá)式中嵌套表函數(shù)調(diào)用,因?yàn)槿魏伪肀磉_(dá)式都可以是表函數(shù)的調(diào)用骗露。例如岭佳,Product表中的以下計(jì)算列僅考慮數(shù)量大于1的銷售額來計(jì)算產(chǎn)品銷售額。
Product[Product Sales Amount Multiple Items] =
SUMX (
FILTER (
RELATEDTABLE ( Sales ),
Sales[Quantity] > 1
),
Sales[Quantity] * Sales[Unit Price]
)
當(dāng)您對(duì)表函數(shù)進(jìn)行嵌套調(diào)用時(shí)萧锉,DAX首先計(jì)算最內(nèi)層函數(shù)珊随,然后計(jì)算其他函數(shù)直到最外層函數(shù)。不要將此規(guī)則與函數(shù)調(diào)用參數(shù)進(jìn)行求值的順序混淆柿隙。
備注:
稍后您將看到叶洞,嵌套調(diào)用的執(zhí)行順序可能會(huì)造成混淆,因?yàn)镃ALCULATETABLE的計(jì)算順序與FILTER不同禀崖。在下一節(jié)中衩辟,您將學(xué)習(xí)FILTER的行為,您將在第5章“理解CALCULATE和CALCULATETABLE”中找到CALCULATETABLE的介紹波附。
2.4 理解FILTER
FILTER函數(shù)有一個(gè)簡(jiǎn)單的角色:它獲取一個(gè)表并返回一個(gè)表惭婿,這個(gè)表的列與原始表中的列相同,但是只包含滿足逐行應(yīng)用的篩選條件的行叶雹。
FILTER的語(yǔ)法如下:
···
FILTER ( <table>, <condition> )
···
FILTER迭代<table>,并且對(duì)于每一行换吧,計(jì)算<condition>折晦,這是一個(gè)布爾表達(dá)式。當(dāng)<condition>的計(jì)算結(jié)果為TRUE時(shí)沾瓦,F(xiàn)ILTER返回該行满着;否則,它會(huì)跳過它贯莺。
備注:
從邏輯上看风喇,F(xiàn)ILTER為<table>中的每一行執(zhí)行<condition>。但是缕探,DAX中的內(nèi)部?jī)?yōu)化可能會(huì)將這些計(jì)算的數(shù)量減少到<condition>表達(dá)式中包含的列引用的唯一值的數(shù)量魂莫。<condition>的實(shí)際計(jì)算次數(shù)對(duì)應(yīng)于FILTER操作的“粒度”。這種粒度決定了FILTER的性能爹耗,它是DAX優(yōu)化的重要元素耙考。
例如谜喊,以下查詢篩選了Fabrikam品牌的產(chǎn)品涯塔,如圖3-6所示汉匙。
EVALUATE
FILTER (
Product,
Product[Brand] = "Fabrikam"
)
您可以在另一個(gè)FILTER函數(shù)中嵌套FILTER調(diào)用毒费,因?yàn)槟梢允褂萌魏伪肀磉_(dá)式作為篩選參數(shù)腹泌。執(zhí)行的第一個(gè)FILTER是最內(nèi)層的拳芙。通常來說薛夜,嵌套兩個(gè)篩選和在AND函數(shù)中使用一組邏輯條件返回的結(jié)果相同袱蚓。換句話說枚碗,以下查詢產(chǎn)生相同的結(jié)果:
FILTER ( <table>, AND ( <condition1>, < condition2> ) )
FILTER ( FILTER ( <table>, < condition1> ), < condition2> ) )
但是逾一,如果<table>有許多行且兩個(gè)判斷條件具有不同的復(fù)雜性,您可能會(huì)觀察到不同的性能视译。例如嬉荆,請(qǐng)考慮以下查詢,該查詢返回Unit Price超過Unit Cost三倍的Fabrikam產(chǎn)品酷含,如圖3-7所示鄙早。
EVALUATE
FILTER (
Product,
AND (
Product[Brand] = "Fabrikam",
Product[Unit Price] > Product[Unit Cost] * 3
))
此類查詢可能會(huì)將這兩個(gè)條件應(yīng)用于Product表的所有行椅亚。如果兩者中有一個(gè)條件更快或更具選擇性限番,則可以使用嵌套的FILTER函數(shù)首先應(yīng)用它。例如呀舔,以下查詢將Unit Price和Unit Cost的篩選應(yīng)用于最里面的FILTER函數(shù)弥虐,然后按品牌篩選那些滿足價(jià)格條件的產(chǎn)品。
EVALUATE
FILTER (
FILTER (
Product,
Product[Unit Price] > Product[Unit Cost] * 3
),
Product[Brand] = "Fabrikam"
)
如果反轉(zhuǎn)條件媚赖,則還會(huì)反轉(zhuǎn)它們的執(zhí)行順序霜瘪。以下查詢將價(jià)格條件應(yīng)用于屬于Fabrikam品牌的產(chǎn)品:
EVALUATE
FILTER (
FILTER (
Product,
Product[Brand] = "Fabrikam"
),
Product[Unit Price] > Product[Unit Cost] * 3
)
當(dāng)您優(yōu)化DAX表達(dá)式時(shí),此知識(shí)將非常有用惧磺。您可以選擇執(zhí)行順序以有限應(yīng)用最具選擇性的篩選器颖对。但是,如果沒有清楚地理解計(jì)算上下文磨隘,請(qǐng)不要開始優(yōu)化DAX缤底。您將在第16章“優(yōu)化DAX”中找到有關(guān)查詢優(yōu)化的更完整的討論。這些示例的目的是讓您了解表函數(shù)的嵌套調(diào)用的執(zhí)行順序番捂。
備注:
通常个唧,嵌套調(diào)用函數(shù)的執(zhí)行順序是從最內(nèi)層到最外層的函數(shù)。您將看到CALCULATE和CALCULATETABLE可能是此行為的一個(gè)例外设预,因?yàn)橛糜谟?jì)算其參數(shù)的特定順序徙歼。因?yàn)槟赡茉陬愃魄闆r下使用FILTER和CALCULATETABLE,所以請(qǐng)注意嵌套調(diào)用的這種差異。
2.5 理解ALL鲁沥、ALLEXCEPT和ALLNOBLANKROW
ALL是一個(gè)有用的函數(shù)呼股,它返回表的所有行或列的所有值,具體取決于您使用的參數(shù)画恰。例如彭谁,以下DAX查詢返回Product表中的所有行:
EVALUATE
ALL ( Product )
您不能在ALL參數(shù)中指定表表達(dá)式。您必須指定表名或列名列表允扇。如果使用單個(gè)列缠局,則結(jié)果是一個(gè)只有一列包含其唯一值列表的表,如圖3-8所示考润。
EVALUATE
ALL ( Product[Class] )
您可以在ALL函數(shù)的參數(shù)中指定同一個(gè)表中的更多列。如果使用多列糊治,則結(jié)果將是具有等效列數(shù)的表唱矛,其中包含這些列中現(xiàn)有值組合的列表。例如井辜,以下表達(dá)式生成如圖3-9所示的結(jié)果绎谦。
EVALUATE
ALL ( Product[Class], Product[Color] )
ORDER BY Product[Color]
在所有變體中粥脚,ALL忽略任何現(xiàn)有的篩選器以產(chǎn)生其結(jié)果窃肠。您可以使用ALL作為迭代函數(shù)的參數(shù),例如SUMX和 FILTER刷允,或者作為CALCULATE函數(shù)中的篩選器參數(shù)(稍后將會(huì)看到)冤留。
如果要在ALL函數(shù)調(diào)用中包含表的大多數(shù)列,則可以使用ALLEXCEPT树灶。ALLEXCEPT的語(yǔ)法需要一個(gè)表纤怒,后跟要從結(jié)果中排除的列。因此天通,ALLEXCEPT返回一個(gè)表泊窘,其中包含表的其他列中現(xiàn)有值組合的唯一列表。
實(shí)際上土砂,ALLEXCEPT是一種編寫DAX表達(dá)式的方法,該表達(dá)式將自動(dòng)在ALL結(jié)果中包含在將來版本中可能出現(xiàn)在表中的任何其他列谜洽。例如萝映,如果您有一個(gè)包含五列(ProductKey、Product Name阐虚、Brand序臂、Class、Color)的Product表,則以下語(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的結(jié)果將忽略它們,而之前的ALLEXCEPT將返回相當(dāng)于:
ALL (
Product[Product Name],
Product[Brand],
Product[Class],
Product[Unit Cost],
Product[Unit Price]
)
以下查詢返回一個(gè)表构订,該表包含Product表中除Product Code和Color之外的所有列侮叮。圖3-10中的結(jié)果與原始表的行數(shù)相同,因?yàn)榻Y(jié)果包含ProductKey列悼瘾,每列具有唯一值囊榜。結(jié)果中列的其他組合可能返回較少的行數(shù),因?yàn)锳LLEXCEPT會(huì)刪除返回列中重復(fù)的值組合亥宿。
EVALUATE ALLEXCEPT ( Product, Product[ProductKey],
Product[Color] )
在前面的示例中,您在EVALUATE語(yǔ)句中看到了ALL烫扼,該語(yǔ)句在沒有任何現(xiàn)有篩選器的情況下執(zhí)行DAX表達(dá)式曙求。因此,最好查看一個(gè)示例映企,該示例使用度量值來計(jì)算數(shù)據(jù)透視表中ALL返回的行數(shù)悟狱,其中每個(gè)單元格使用不同的篩選器計(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”列中始終具有相同的編號(hào)。 ALL語(yǔ)句的計(jì)算將忽略由數(shù)據(jù)透視表的每個(gè)單元格定義的篩選器掷邦。
在關(guān)系的父表上調(diào)用ALL時(shí)白胀,如果子表包含一個(gè)或多個(gè)與父表中的任何值不匹配的行,則會(huì)檢索另一個(gè)空行抚岗。您可以使用ALLNOBLANKROW而不是ALL來從結(jié)果中省略此特殊行或杠。
考慮以下度量值:
[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中,您可以看到度量值A(chǔ)LL和ALLNOBLANKROW之間的區(qū)別宣蔚。所有版本的度量值A(chǔ)LL都比ALLNOBLANKROW多一行向抢。原因是Sales表中的部分行在Product表中沒有匹配的行,因此在Product表中虛擬添加了一行胚委,您可以在圖3-12中的(空白)行中看到該結(jié)果挟鸠。
您應(yīng)該注意到艘希,All Sizes和All NoBlank Sizes度量值始終返回相同的值。此度量值查詢Products [Size]列中的值的計(jì)數(shù)。在這種情況下覆享,ALL和ALLNOBLANKROW函數(shù)返回相同的值佳遂,因?yàn)镻roducts [Size]列已包含空值。在圖3-13中的示例中撒顿,有569個(gè)產(chǎn)品的Products [Size]是空白丑罪,另外還有一類空白產(chǎn)品,包含對(duì)Sales表中不匹配產(chǎn)品的引用核蘸,總共570個(gè)巍糯。所有這些行都?xì)w為Products [Size]中的空白值。
當(dāng)你編寫一個(gè)DAX公式,該公式忽略關(guān)系中的不匹配值徙鱼,你應(yīng)該使用ALLNOBLANKROW宅楞。然而,ALL的使用很常見袱吆,而ALLNOBLANKROW很少使用厌衙。
2.6 理解VALUES和DISTINCT
在上一節(jié)中,您已經(jīng)看到ALL與一列一起使用會(huì)返回一個(gè)包含其所有唯一值的表绞绒。 DAX提供了另外兩個(gè)類似的函數(shù)婶希,它們返回列的唯一值列表:VALUES和DISTINCT。
如果在沒有任何其他篩選器操作的EVALUATE語(yǔ)句中使用蓬衡,則VALUES和DISTINCT看起來與ALL完全相同喻杈。但是,當(dāng)您將這些函數(shù)放在DAX度量值中時(shí)狰晚,您可以觀察到不同的行為筒饰,因?yàn)橛?jì)算發(fā)生在數(shù)據(jù)透視表的每個(gè)單元格的不同上下文中。
請(qǐng)考慮以下度量值壁晒,這些度量值計(jì)算“Product”表的“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執(zhí)行相同操作谬晕,而不包括不匹配值的可選空行。但是携取,如果空白值顯示為列的有效值攒钳,則2個(gè)函數(shù)都將包含空行。唯一的區(qū)別是為了處理關(guān)系中的缺失值而添加的可選空行歹茶。
一個(gè)例子可能有助于理解這種差異夕玩。如圖3-14所示,每個(gè)產(chǎn)品類別都會(huì)篩選不同數(shù)量的產(chǎn)品惊豺。例如燎孟,Deluxe類別有360種產(chǎn)品,有11個(gè)獨(dú)特品牌和204種獨(dú)特尺寸尸昧。 VALUES和DISTINCT返回相同的數(shù)字揩页,但有一個(gè)例外:數(shù)據(jù)透視表行上的(空白)產(chǎn)品類別。結(jié)果包括為顯示不匹配產(chǎn)品的銷售額金額而添加的虛擬行烹俗。
另一個(gè)區(qū)別在于圖3-14的總計(jì)幢妄。應(yīng)用于Product [Brand]的VALUES返回的值比應(yīng)用于同一列的DISTINCT多一個(gè)值兔仰。但是,應(yīng)用于Products [Size]的VALUES不會(huì)發(fā)生這種情況蕉鸳,它返回與相應(yīng)列上的DISTINCT相同的值乎赴。原因是至少一個(gè)產(chǎn)品的“Distinct Sizes”列包含空值,因此添加的空白產(chǎn)品不會(huì)向“Distinct Sizes”列添加新的唯一值潮尝。
當(dāng)沒有篩選器時(shí)榕吼,DISTINCT的行為對(duì)應(yīng)于ALLNOBLANKROW,而VALUES的行為對(duì)應(yīng)于ALL勉失。
VALUES也接受一個(gè)表作為參數(shù)羹蚣。在這種情況下,它返回當(dāng)前單元格中可見的整個(gè)表乱凿,可選地包括不匹配關(guān)系的空行顽素。例如,在數(shù)據(jù)模型中考慮以下度量值告匠,其中Sales表與Product具有關(guān)系戈抄,并且包含具有與任何現(xiàn)有產(chǎn)品不匹配的產(chǎn)品密鑰的交易。
[Products] := COUNTROWS ( Product )
[Values Products] := COUNTROWS ( VALUES ( Product ) )
[All NoBlank Products] := COUNTROWS ( ALLNOBLANKROW ( Product
) )
[All Products] := COUNTROWS ( ALL ( Product ) )
您可以在圖3-15中看到后专,在這種情況下划鸽,當(dāng)沒有篩選器時(shí),VALUES的結(jié)果對(duì)應(yīng)于ALL的行為戚哎,包括添加的空行以顯示不匹配產(chǎn)品的銷售額裸诽。在這種情況下,您不能在表上使用DISTINCT型凳;如果存在重復(fù)的行丈冬,則沒有一個(gè)DAX函數(shù)可以刪除重復(fù)的行(您必須使用SUMMARIZE,稍后將在第9章中看到)甘畅。但是埂蕊,度量值[Products]計(jì)算表中的行數(shù)往弓,忽略可能的空行,當(dāng)沒有篩選器時(shí)蓄氧,對(duì)應(yīng)ALLNOBLANKROW函似。
2.6.3 使用VALUES作為標(biāo)量值
即使VALUES是表函數(shù)喉童,您也經(jīng)常使用它來計(jì)算標(biāo)量值撇寞,因?yàn)槟鷮⒃诒竟?jié)中學(xué)習(xí)DAX中的特殊功能。例如堂氯,您可以在以下表達(dá)式中找到VALUES蔑担,如果某個(gè)選擇的所有產(chǎn)品具有相同的顏色,則會(huì)顯示顏色名稱:
[Color Name] :=
IF (
COUNTROWS ( VALUES ( Product[Color] ) ) = 1,
VALUES ( Product[Color] )
)
您可以在圖3-16中看到結(jié)果咽白。當(dāng)“[Color Name]”列包含空白時(shí)啤握,表示存在兩種或更多種不同的顏色。
這里有趣的一點(diǎn)是三妈,我們使用VALUES的結(jié)果作為標(biāo)量值畜埋,即使它返回一個(gè)表。這不是VALUES的特殊行為畴蒲,但它是DAX語(yǔ)言的更一般行為:如果表表達(dá)式返回具有一行和一列的表悠鞍,則可以轉(zhuǎn)換為標(biāo)量值,并在需要時(shí)自動(dòng)完成模燥。
實(shí)際上咖祭,如果結(jié)果只有一行和一列,則可以將任何表表達(dá)式用作標(biāo)量值蔫骂。當(dāng)表返回更多行時(shí)么翰,您會(huì)在執(zhí)行時(shí)收到此錯(cuò)誤:“提供了一個(gè)包含多個(gè)值的表,其中需要單個(gè)值辽旋『葡樱”因此,您應(yīng)始終使用返回的條件保護(hù)轉(zhuǎn)換為標(biāo)量值如果表表達(dá)式返回更多行补胚,則表示不同的結(jié)果(在編寫DAX表達(dá)式時(shí)码耐,您應(yīng)該已經(jīng)知道表表達(dá)式是否只返回一行)。
上一個(gè)示例的Color Name度量值使用COUNTROWS來檢查Products表的Color列是否只選擇了一個(gè)值溶其。執(zhí)行完全相同控件的一種更簡(jiǎn)單的方法是使用HASONEVALUE骚腥,它執(zhí)行相同的檢查,如果列只有VALUES返回的值瓶逃,則返回TRUE束铭,否則返回FALSE廓块。以下兩種語(yǔ)法是等效的:
COUNTROWS ( VALUES ( <column> ) ) = 1
HASONEVALUE ( <column> )
您應(yīng)該使用HASONEVALUE而不是COUNTROWS有兩個(gè)原因:它更具可讀性,而且可能稍快一些契沫。以下是基于HASONEVALUE的[Color Name]度量值的更好實(shí)現(xiàn):
[Color Name] :=
IF (
HASONEVALUE ( Product[Color] ),
VALUES ( Product[Color] )
)
您經(jīng)常使用VALUES作為標(biāo)量表達(dá)式的原因是它返回單個(gè)列剿骨,并且可能返回單個(gè)行,具體取決于計(jì)算上下文埠褪。使用VALUES作為標(biāo)量表達(dá)式在許多DAX模式中很常見,并且在本書中反復(fù)出現(xiàn)挤庇。