現(xiàn)在商模,您已經(jīng)學(xué)習(xí)了DAX語(yǔ)言的基礎(chǔ)知識(shí)山析。您知道如何創(chuàng)建計(jì)算列和度量值订框,并且您對(duì)DAX中的常用函數(shù)有很好的理解链嘀。本章將帶你進(jìn)入DAX語(yǔ)言的更高級(jí)別:在學(xué)習(xí)了扎實(shí)的DAX語(yǔ)言理論基礎(chǔ)之后懂版,您將能夠成為一個(gè)真正的DAX冠軍鹃栽。
根據(jù)當(dāng)前所獲得的知識(shí),您已經(jīng)可以創(chuàng)建許多有趣的報(bào)告躯畴,但您需要學(xué)習(xí)計(jì)算上下文以創(chuàng)建更復(fù)雜的報(bào)告民鼓。計(jì)算上下文是DAX所有高級(jí)功能的基礎(chǔ)。
我們想向讀者說(shuō)幾句警告:計(jì)算上下文的概念很簡(jiǎn)單蓬抄,您很快就會(huì)學(xué)到并理解它丰嘉。然而,您需要徹底了解幾個(gè)微妙的注意事項(xiàng)和細(xì)節(jié)嚷缭。否則饮亏,在學(xué)習(xí)DAX的過(guò)程中耍贾,你會(huì)在某一點(diǎn)上感到迷茫。我們?cè)诠埠退饺苏n程中教授DAX給許多用戶路幸。我們知道這絕對(duì)正常荐开。在某個(gè)時(shí)刻 ,你感覺(jué)公式像魔術(shù)一樣工作简肴,因?yàn)樗鼈兤鹱饔檬慕梗悴幻靼诪槭裁础e擔(dān)心:很多人都會(huì)經(jīng)歷這個(gè)過(guò)程着帽。大多數(shù)DAX學(xué)生已經(jīng)達(dá)到了這一點(diǎn)杂伟,而其他許多學(xué)生將來(lái)也會(huì)達(dá)到這一點(diǎn)。這只是意味著他們不夠了解計(jì)算上下文仍翰。那時(shí)赫粥,很簡(jiǎn)單:回到這一章,再讀一遍予借,你可能會(huì)發(fā)現(xiàn)一些新的東西越平,這是你第一次讀的時(shí)候錯(cuò)過(guò)的。
此外灵迫,計(jì)算上下文在使用函數(shù)CALCULATE時(shí)發(fā)揮了重要作用秦叛,這可能是DAX中功能最強(qiáng)大且難以學(xué)習(xí)的函數(shù)。我們將在第5章“理解CALCULATE和CALCULATETABLE”中介紹CALCULATE瀑粥,然后在本書的其余部分中使用它挣跋。在沒(méi)有扎實(shí)的計(jì)算上下文知識(shí)的情況下理解CALCULATE是有問(wèn)題的。另一方面狞换,在不嘗試使用CALCULATE的情況下理解計(jì)算上下文的重要性幾乎是不可能的避咆。因此,根據(jù)我們之前編寫的書籍的經(jīng)驗(yàn)修噪,本章下一章將會(huì)被反復(fù)閱讀查库。
4.1 計(jì)算上下文簡(jiǎn)介
讓我們從理解計(jì)算上下文是什么開(kāi)始。所有DAX表達(dá)式在一個(gè)上下文環(huán)境中計(jì)算黄琼。上下文是計(jì)算公式的“環(huán)境”樊销。例如,考慮一個(gè)非常簡(jiǎn)單的度量值公式:
[Sales Amount] := SUMX ( Sales, Sales[Quantity] * Sales[UnitPrice] )
您已經(jīng)知道此公式計(jì)算的內(nèi)容:Sales表中所有數(shù)量值乘以價(jià)格的總和脏款。您可以將此度量值放在數(shù)據(jù)透視表中并查看結(jié)果围苫,如圖4-1所示。
嗯够吩,這個(gè)數(shù)字本身看起來(lái)并不有趣比然,是嗎丈氓?但是,如果你仔細(xì)思考,公式就會(huì)計(jì)算出它應(yīng)該計(jì)算的內(nèi)容:所有銷售額的合計(jì)万俗,這是一個(gè)沒(méi)有意義的大數(shù)字湾笛。當(dāng)我們使用一些列來(lái)切割總計(jì)并查看它,這個(gè)數(shù)據(jù)透視表就會(huì)變得更有趣闰歪。例如嚎研,您可以獲取產(chǎn)品顏色,將其放在行上库倘,并且數(shù)據(jù)透視表突然顯示一些有趣的業(yè)務(wù)見(jiàn)解临扮,如圖4-2所示。
總計(jì)仍然存在杆勇,但現(xiàn)在它是較小值的合計(jì),每個(gè)值饱亿,連同所有其他值蚜退,都有意義。但是彪笼,如果你再仔細(xì)思考钻注,你應(yīng)該注意到這個(gè)不可思議的事情:公式并沒(méi)有計(jì)算我們要求的東西。
我們認(rèn)為該公式意味著“所有銷售額的總和配猫》担”但是在數(shù)據(jù)透視表的每個(gè)單元格內(nèi),公式不是計(jì)算所有銷售額的總和泵肄,而是僅計(jì)算具有特定顏色的產(chǎn)品的銷售總和佳遣。然而,我們從未指定計(jì)算必須在數(shù)據(jù)模型的子集上工作凡伊。換句話說(shuō)零渐,該公式未指定它可以處理數(shù)據(jù)子集。
為什么公式在不同的單元格中計(jì)算不同的值系忙?答案非常簡(jiǎn)單:因?yàn)樵谟?jì)算上下文環(huán)境中DAX計(jì)算公式诵盼。您可以將公式的計(jì)算上下文視為DAX計(jì)算公式的單元格周圍區(qū)域。
因?yàn)閜roduct顏色在行上银还,數(shù)據(jù)透視表中的每一行都可以看到风宁,從整個(gè)數(shù)據(jù)庫(kù)中,只有特定顏色的product的子集蛹疯。這是公式的周圍區(qū)域戒财,即在公式計(jì)算之前應(yīng)用于數(shù)據(jù)庫(kù)的一組篩選器。當(dāng)公式計(jì)算所有銷售額的總和時(shí)捺弦,它不會(huì)在整個(gè)數(shù)據(jù)庫(kù)中計(jì)算它饮寞,因?yàn)樗鼪](méi)有查看所有行的選項(xiàng)孝扛。當(dāng)DAX在值為White的行中的計(jì)算公式時(shí),只有白色產(chǎn)品是可見(jiàn)的幽崩,因此苦始,它只考慮與白色產(chǎn)品相關(guān)的銷售。所以慌申,當(dāng)計(jì)算透視表中的一行僅顯示白色產(chǎn)品時(shí)陌选,所有銷售額的總和將成為白色產(chǎn)品的所有銷售額的總和。
任何DAX公式都指定一個(gè)計(jì)算蹄溉,但DAX在上下文中計(jì)算公式咨油,該上下文定義最終計(jì)算的值。公式總是相同柒爵,但值不同臼勉,因?yàn)镈AX根據(jù)不同的數(shù)據(jù)子集對(duì)其進(jìn)行計(jì)算。
公式在其定義方式中表現(xiàn)的唯一情況是總計(jì)餐弱。在該級(jí)別宴霸,因?yàn)闆](méi)有發(fā)生篩選,所以整個(gè)數(shù)據(jù)庫(kù)都是可見(jiàn)的膏蚓。
備注:
在這些示例中瓢谢,為簡(jiǎn)單起見(jiàn),我們使用數(shù)據(jù)透視表驮瞧。顯然氓扛,您也可以使用查詢定義計(jì)算上下文,您將在以后的章節(jié)中了解有關(guān)它的更多信息÷郾剩現(xiàn)在采郎,最好保持簡(jiǎn)單并僅考慮數(shù)據(jù)透視表,以便對(duì)概念有一個(gè)簡(jiǎn)化和可視化的理解狂魔。
現(xiàn)在讓我們把年份放在列上蒜埋,使數(shù)據(jù)透視表更加有趣。該報(bào)告現(xiàn)在如圖4-3所示最楷。
此時(shí)游戲規(guī)則應(yīng)該清楚:即使公式始終相同,每個(gè)單元格現(xiàn)在也有不同的值籽孙,因?yàn)閿?shù)據(jù)透視表的行和列選擇都定義了上下文烈评。事實(shí)上,2008年白色產(chǎn)品的銷售額與2007年白色產(chǎn)品的銷售額不同犯建。此外讲冠,因?yàn)槟梢栽谛泻土兄蟹胖枚鄠€(gè)字段,所以最好說(shuō)行上的字段集和列上的字段集定義上下文适瓦。圖4-4使這一點(diǎn)更加明顯竿开。
每個(gè)單元格都有不同的值,因?yàn)樾猩嫌袃蓚€(gè)字段:顏色和品牌名德迹。行和列上的完整字段集定義了上下文。例如揭芍,圖4-4中突出顯示的單元格的上下文對(duì)應(yīng)于黑色胳搞、品牌Contoso和Calendar Year 2007。
備注:
字段是在行上還是在列上(或者在切片器和/或頁(yè)面篩選器上称杨,或者您可以使用查詢創(chuàng)建的任何其他類型的篩選器)并不重要肌毅。所有這些篩選器都有助于定義單個(gè)上下文,DAX用它來(lái)計(jì)算公式姑原。在行或列上放置一個(gè)字段只會(huì)產(chǎn)生一些可視效果悬而,但DAX計(jì)算值的方式?jīng)]有任何變化。
我們現(xiàn)在看看全貌锭汛。在圖4-5中笨奠,我們?cè)谇衅魃咸砑恿水a(chǎn)品類別,并在過(guò)濾器上添加了月份名稱唤殴,我們選擇了12月般婆。
很明顯,每個(gè)單元格中計(jì)算的值都有一個(gè)由行配名、列啤咽、切片器和篩選器定義的上下文。所有這些篩選器都有助于定義DAX在公式計(jì)算之前應(yīng)用于數(shù)據(jù)模型的上下文渠脉。此外宇整,重要的是要知道并非所有單元都具有相同的篩選器組,不僅在值方面芋膘,而且在字段方面没陡。例如,列上的總計(jì)僅包含類別索赏、月份和年份的篩選器盼玄,但它不包含顏色和品牌的篩選器。顏色和品牌的字段在行上潜腻,并且不會(huì)過(guò)濾總計(jì)埃儿。這同樣適用于數(shù)據(jù)透視表中的顏色小計(jì):對(duì)于那些單元格,制造商沒(méi)有篩選器融涣,來(lái)自行的唯一有效篩選器是顏色童番。
我們將此上下文稱為篩選上下文精钮,顧名思義,它是一個(gè)篩選表的上下文剃斧。根據(jù)DAX用于執(zhí)行其計(jì)算的篩選器上下文轨香,您所編寫的任何公式都將具有不同的值。盡管這種行為非常直觀幼东,但任需要很好地理解臂容。
現(xiàn)在您已經(jīng)了解了篩選上下文的內(nèi)容,您知道以下DAX表達(dá)式應(yīng)該被理解為“當(dāng)前篩選上下文中可見(jiàn)的所有銷售額的總和”:
[Sales Amount] := SUMX ( Sales, Sales[Quantity] * Sales[UnitPrice] )
稍后您將學(xué)習(xí)如何閱讀根蟹、修改和清除篩選器上下文脓杉。截至目前,您已經(jīng)充分了解篩選上下文始終存在于數(shù)據(jù)透視表的任何單元格和報(bào)表/查詢中的任何值這一事實(shí)就足夠了简逮。您始終需要考慮篩選上下文球散,以了解DAX如何計(jì)算公式。
4.1.1 理解行上下文
篩選上下文是DAX中存在的兩個(gè)上下文之一散庶。它的伴侶是行上下文蕉堰,在本節(jié)中,您將了解行上下文是什么以及它是如何工作的悲龟。
這一次嘁灯,我們使用不同的公式來(lái)研究:
Sales[GrossMargin] = Sales[SalesAmount] - Sales[TotalCost]
您可能會(huì)在計(jì)算列中編寫此表達(dá)式,以計(jì)算毛利率躲舌。只要在計(jì)算列中定義此公式丑婿,就會(huì)得到結(jié)果表熊赖,如圖4-6所示捌浩。
DAX計(jì)算了表的所有行的公式遮斥,并且對(duì)于每一行谈竿,它按預(yù)期計(jì)算了不同的值苍糠。為了理解行上下文疫向,我們?cè)陂喿x公式時(shí)需要有點(diǎn)迂腐:我們要求減去兩列众辨,但是我們從哪里告訴DAX從哪一行獲取列的值煤蚌?您可能會(huì)說(shuō)要使用的行是隱式的耕挨。因?yàn)樗且粋€(gè)計(jì)算列,DAX會(huì)逐行計(jì)算它尉桩,并且對(duì)于每一行筒占,它會(huì)計(jì)算不同的結(jié)果。這是正確的蜘犁,但是翰苫,從DAX表達(dá)式的角度來(lái)看,仍然缺少有關(guān)使用哪一行的信息。
實(shí)際上奏窑,用于執(zhí)行計(jì)算的行不存儲(chǔ)在公式中导披。它由另一種上下文定義:行上下文。當(dāng)您定義計(jì)算列時(shí)埃唯,DAX從表的第一行開(kāi)始迭代撩匕;它創(chuàng)建了一個(gè)包含該行的行上下文并計(jì)算了表達(dá)式。然后它移動(dòng)到第二行并再次計(jì)算表達(dá)式墨叛。對(duì)于表中的所有行都會(huì)發(fā)生這種情況止毕,如果您有一百萬(wàn)行,您可以認(rèn)為DAX創(chuàng)建了一百萬(wàn)行上下文來(lái)評(píng)估公式一百萬(wàn)次巍实。顯然滓技,為了優(yōu)化計(jì)算哩牍,這并不是實(shí)際情況棚潦;否則,DAX將是一種非常慢的語(yǔ)言膝昆。
無(wú)論如何丸边,從邏輯的角度來(lái)看,這正是它的工作原理荚孵。
讓我們?cè)囍f(shuō)得更精確些妹窖。行上下文是始終包含單行的上下文,DAX在創(chuàng)建計(jì)算列時(shí)自動(dòng)定義它收叶。您可以使用其他方法創(chuàng)建行上下文骄呼,這將在本章后面討論,但解釋行上下文的最簡(jiǎn)單方法是查看計(jì)算列判没,引擎始終自動(dòng)創(chuàng)建它蜓萄。
總有兩個(gè)上下文
目前為止,您已經(jīng)了解了行上下文和篩選上下文澄峰。它們是DAX中唯一的上下文嫉沽。因此,它們是修改公式結(jié)果的唯一方法俏竞。任何公式都將在這兩個(gè)不同的上下文中進(jìn)行計(jì)算:行上下文和篩選上下文绸硕。
我們將這兩種上下文稱為“計(jì)算上下文”,因?yàn)樗鼈兪歉淖児接?jì)算方式的上下文魂毁,為相同公式提供不同的結(jié)果玻佩。
這一點(diǎn)非常重要,而且在開(kāi)始時(shí)很難集中注意:總是有兩種上下文席楚,公式的結(jié)果取決于這兩種上下文夺蛇。在DAX學(xué)習(xí)路徑的這一點(diǎn)上,您可能認(rèn)為這是顯而易見(jiàn)且非常自然的酣胀。你可能是對(duì)的刁赦。然而娶聘,在本書的后面,您將發(fā)現(xiàn)甚脉,如果您不記得這兩種上下文的共存關(guān)系丸升,那么要理解這些公式將是一個(gè)挑戰(zhàn),因?yàn)檫@兩種上下文都可以更改公式的結(jié)果牺氨。
4.2 測(cè)試你對(duì)上下文的理解
在我們進(jìn)行關(guān)于計(jì)算上下文的更復(fù)雜的討論之前狡耻,我們想用幾個(gè)例子來(lái)測(cè)試你對(duì)上下文的理解。請(qǐng)不要立即查看說(shuō)明猴凹;在問(wèn)題之后停下來(lái)并嘗試回答它夷狰。然后閱讀解釋以理解它。
4.2.1 在計(jì)算列中使用SUM函數(shù)
第一個(gè)測(cè)試非常簡(jiǎn)單郊霎。如果使用此代碼在Sales中定義計(jì)算列沼头,會(huì)發(fā)生什么?
Sales[SumOfSalesAmount] = SUM ( Sales[SalesAmount] )
因?yàn)樗且粋€(gè)計(jì)算列书劝,所以它將逐行計(jì)算进倍,對(duì)于每一行,您將獲得一個(gè)結(jié)果购对。你期望看到什么數(shù)字猾昆?從以下選項(xiàng)中選擇一個(gè):
- 該行的SalesAmount值,即每行的不同值骡苞。
- 所有行的SalesAmount總數(shù)垂蜗,即所有行的相同值。
- 一個(gè)錯(cuò)誤;您不能在計(jì)算列中使用SUM解幽。
請(qǐng)停止閱讀贴见,我們?cè)诘饶阌懈鶕?jù)的猜測(cè)后再繼續(xù)。
現(xiàn)在亚铁,讓我們?cè)敿?xì)說(shuō)明DAX計(jì)算公式時(shí)發(fā)生了什么蝇刀。您已經(jīng)了解了公式含義:“當(dāng)前篩選器上下文中顯示的所有銷售額的總和∨且纾”由于這是在計(jì)算列中吞琐,DAX逐行計(jì)算公式。因此然爆,它為第一行創(chuàng)建行上下文站粟,然后調(diào)用公式計(jì)算并繼續(xù)迭代整個(gè)表。該公式計(jì)算當(dāng)前篩選器上下文中所有銷售額值的總和曾雕,因此真正的問(wèn)題是“當(dāng)前篩選上下文是什么奴烙?”答案:它是完整數(shù)據(jù)庫(kù),它是完整的數(shù)據(jù)庫(kù),因?yàn)镈AX在任何數(shù)據(jù)透視表或任何其他類型的篩選之外計(jì)算公式切诀。事實(shí)上揩环,當(dāng)沒(méi)有過(guò)篩選時(shí),DAX會(huì)將其計(jì)算為計(jì)算列定義的一部分幅虑。
即使存在行上下文丰滑,SUM也會(huì)忽略它。相反倒庵,它使用篩選上下文褒墨,現(xiàn)在篩選上下文是完整數(shù)據(jù)庫(kù)。因此擎宝,第二個(gè)選項(xiàng)是正確的:您將獲得銷售額的總計(jì)郁妈,所有行的值相同,如圖4-7所示绍申。
這個(gè)例子表明這兩個(gè)上下文同時(shí)存在。它們都對(duì)一個(gè)公式的結(jié)果進(jìn)行處理失晴,但方式不同剧腻。計(jì)算列中使用的SUM拘央、MIN和MAX等聚合函數(shù)僅使用篩選上下文涂屁,并忽略行上下文,DAX僅使用行上下文來(lái)確定列值灰伟。如果您選擇了第一個(gè)答案拆又,就像許多學(xué)生一樣,這是完全正常的栏账。關(guān)鍵是帖族,您還沒(méi)有考慮到這兩個(gè)上下文正在以不同的方式一起工作來(lái)更改公式的結(jié)果。第一個(gè)答案是最常見(jiàn)的挡爵,直覺(jué)上是竖般,但它是錯(cuò)誤的,現(xiàn)在你知道為什么茶鹃。
4.2.2 在度量值中使用列
第二個(gè)測(cè)試有點(diǎn)不同涣雕。想象一下,您想要在度量值而不是計(jì)算列中定義毛利率的公式闭翩。您有一個(gè)包含銷售額的列挣郭,另一列包含產(chǎn)品成本,您可以編寫以下表達(dá)式:
[GrossMargin] := Sales[SalesAmount] - Sales[ProductCost]
如果您嘗試編寫此度量值疗韵,您會(huì)得到什么結(jié)果兑障?
- 表達(dá)式正常,我們需要在報(bào)告中測(cè)試結(jié)果。
- 一個(gè)錯(cuò)誤流译,你甚至不能創(chuàng)作這個(gè)公式逞怨。
- 您可以定義公式,但在數(shù)據(jù)透視表或查詢中使用時(shí)會(huì)出錯(cuò)福澡。
和以前一樣骇钦,停止閱讀,考慮答案竞漾,然后閱讀以下說(shuō)明眯搭。
在公式中,我們使用Sales [SalesAmount]业岁,它是一個(gè)列名鳞仙,即Sales表中SalesAmount的值。這個(gè)定義缺少什么嗎笔时?您應(yīng)該從前面的參數(shù)中回憶一下棍好,此處缺少的信息是從哪里獲取SalesAmount的當(dāng)前值的行。當(dāng)您在計(jì)算列中編寫這段代碼時(shí)允耿,由于行上下文的關(guān)系借笙,DAX在計(jì)算表達(dá)式時(shí)知道要使用的行。但是较锡,度量值會(huì)發(fā)生什么业稼?沒(méi)有迭代,沒(méi)有當(dāng)前行蚂蕴,也就是說(shuō)低散,沒(méi)有行上下文。
因此骡楼,第二個(gè)答案是正確的熔号。你甚至不能寫公式;它在語(yǔ)法上是錯(cuò)誤的鸟整,當(dāng)你嘗試輸入它時(shí)會(huì)收到錯(cuò)誤引镊。
請(qǐng)記住,列本身沒(méi)有值篮条。相反弟头,它對(duì)表的每一行都有不同的值。因此兑燥,如果您想要單個(gè)值亮瓷,則需要指定要使用的行。指定要使用的行的唯一方法是行上下文降瞳。因?yàn)樵谶@個(gè)度量值中沒(méi)有行上下文嘱支,所以公式是不正確的蚓胸,DAX將拒絕它。
在度量值中指定此計(jì)算的正確方法是使用聚合函數(shù)除师,如:
[GrossMargin]:= SUM(Sales [SalesAmount]) - SUM(Sales [ProductCost])
使用此公式沛膳,您現(xiàn)在要求通過(guò)SUM進(jìn)行聚合。因此汛聚,后一個(gè)公式不依賴于行上下文锹安;它只需要一個(gè)篩選上下文,它提供了正確的結(jié)果倚舀。
4.3 使用迭代器創(chuàng)建行上下文
您了解到DAX在您定義計(jì)算列時(shí)會(huì)自動(dòng)創(chuàng)建行上下文叹哭。在這種情況下,引擎會(huì)逐行評(píng)估DAX表達(dá)式『勖玻現(xiàn)在风罩,是時(shí)候?qū)W習(xí)如何使用迭代器在DAX表達(dá)式中創(chuàng)建行上下文。
您可能還記得第2章“DAX簡(jiǎn)介”中所說(shuō)的舵稠,所有X結(jié)尾函數(shù)都是迭代器仑最,也就是說(shuō)喧务,它們遍歷表并為每行計(jì)算表達(dá)式帅腌,最后使用不同的算法聚合結(jié)果蹂季。例如,查看以下DAX表達(dá)式:
[IncreasedSales] := SUMX ( Sales, Sales[SalesAmount] * 1.1 )
SUMX是一個(gè)迭代器落追,它迭代Sales表盈滴,并且對(duì)于表的每一行,它計(jì)算銷售額增加10%到它的值淋硝,最后返回所有這些值的總和雹熬。為了計(jì)算每一行的表達(dá)式宽菜,SUMX在Sales表上創(chuàng)建一個(gè)行上下文谣膳,并在迭代期間使用它。
DAX在包含當(dāng)前迭代行的行上下文中計(jì)算內(nèi)部表達(dá)式(SUMX的第二個(gè)參數(shù))铅乡。
值得注意的是继谚,SUMX的不同參數(shù)在完整計(jì)算流程中使用不同的上下文。讓我們仔細(xì)看看這個(gè)表達(dá)式:
= SUMX (
Sales, ←外部上下文
Sales[SalesAmount] * 1.1 ← 外部上下文 + 新行上下文
)
第一個(gè)參數(shù)Sales使用來(lái)自調(diào)用者的上下文進(jìn)行計(jì)算(例如阵幸,它可能是一個(gè)pivot表單元格花履、另一個(gè)度量或查詢的一部分),而第二個(gè)參數(shù)(表達(dá)式)則使用外部上下文和新創(chuàng)建的行上下文進(jìn)行計(jì)算挚赊。
所有迭代器的行為方式都相同:
- 為作為第一個(gè)參數(shù)接收的表的每一行創(chuàng)建一個(gè)新的行上下文诡壁。
- 評(píng)估新創(chuàng)建的行上下文中的第二個(gè)參數(shù)(以及迭代開(kāi)始之前存在的任何其他上下文),對(duì)于表的每一行荠割。
- 聚合在步驟2中計(jì)算的值妹卿。
重要的是要記住原始上下文在表達(dá)式中仍然有效:迭代器只添加一個(gè)新的行上下文旺矾,他們不會(huì)以任何方式修改現(xiàn)有的上下文。此規(guī)則通常有效夺克,但有一個(gè)重要的例外:如果先前的上下文已經(jīng)包含了同一表的行上下文箕宙,那么新創(chuàng)建的行上下文將隱藏先前存在的行上下文。我們將在下一節(jié)中更詳細(xì)地討論這個(gè)問(wèn)題铺纽。
4.3.1 使用EARLIER函數(shù)
在同一個(gè)表上有許多嵌套行上下文的情況似乎非常罕見(jiàn)柬帕,但實(shí)際上,它經(jīng)常發(fā)生狡门。讓我們以一個(gè)例子來(lái)看這個(gè)概念陷寝。想象一下,您希望為每種產(chǎn)品計(jì)算價(jià)格較高的其他產(chǎn)品的數(shù)量其馏。這將根據(jù)價(jià)格產(chǎn)生一種產(chǎn)品排名盼铁。
為了解決這個(gè)問(wèn)題,我們使用您在前一章中學(xué)到的FILTER函數(shù)尝偎。您可能還記得饶火,F(xiàn)ILTER是一個(gè)迭代器,它循環(huán)遍歷表的所有行致扯,并返回一個(gè)新表肤寝,其中只包含滿足第二個(gè)參數(shù)定義的條件的行。例如抖僵,如果要檢索價(jià)格高于100美元的產(chǎn)品表鲤看,可以使用:
= FILTER ( Product, Product[UnitPrice] > 100 )
備注:
細(xì)心的讀者會(huì)注意到FILTER需要是一個(gè)迭代器,因?yàn)楫?dāng)且僅當(dāng)Product存在有效的行上下文時(shí)耍群,才能計(jì)算表達(dá)式Product [UnitPrice]> 100义桂;否則Unit Price的實(shí)際值將是不確定的。 FILTER是一個(gè)迭代器函數(shù)蹈垢,它在第一個(gè)參數(shù)中為表的每一行創(chuàng)建一個(gè)行上下文慷吊,這樣就可以在第二個(gè)參數(shù)中計(jì)算條件。
現(xiàn)在曹抬,讓我們回到我們?cè)瓉?lái)的例子:創(chuàng)建一個(gè)計(jì)算列溉瓶,它計(jì)算價(jià)格高于當(dāng)前價(jià)格的產(chǎn)品數(shù)量。
如果您要命名當(dāng)前產(chǎn)品PriceOfCurrentProduct的價(jià)格谤民,那么很容易看出這個(gè)偽DAX公式可以滿足需要:
Product[UnitPriceRank] =
COUNTROWS (
FILTER (
Product,
Product[UnitPrice] > PriceOfCurrentProduct
))
FILTER僅返回價(jià)格高于當(dāng)前價(jià)格的產(chǎn)品堰酿,COUNTROWS會(huì)對(duì)這些產(chǎn)品進(jìn)行計(jì)數(shù)。唯一剩下的問(wèn)題是表達(dá)當(dāng)前產(chǎn)品價(jià)格的方法张足,用有效的DAX語(yǔ)法替換PriceOfCurrentProduct触创。對(duì)于“當(dāng)前”,我們指的是當(dāng)DAX計(jì)算列時(shí)當(dāng)前行中列的值为牍。它比你想象的要難哼绑。
您可以在Product表中定義此新計(jì)算列顺饮。因此,DAX計(jì)算行上下文中的表達(dá)式凌那。但是兼雄,表達(dá)式使用FILTER在同一個(gè)表上創(chuàng)建新的行上下文。實(shí)際上帽蝶,在上一個(gè)表達(dá)式的第五行中使用的Product [UnitPrice]是FILTER迭代(我們的內(nèi)部迭代)的當(dāng)前行的單價(jià)的值赦肋。因此,此新行上下文隱藏了由計(jì)算列引入的原始行上下文励稳。你看到了這個(gè)問(wèn)題嗎佃乘?您想要訪問(wèn)單價(jià)的當(dāng)前值,但不使用上次引入的行上下文驹尼。相反趣避,您希望使用前面計(jì)算列創(chuàng)建的行上下文。
DAX提供了一個(gè)使之成為可能的函數(shù):EARLIER新翎。 EARLIER使用前一行上下文而不是新的行上下文來(lái)檢索列的值程帕。因此,您可以使用EARLIER(Product [UnitPrice])表達(dá)PriceOfCurrentProduct的值地啰。
EARLIER是DAX中最奇怪的功能之一愁拭。很多用戶都對(duì)EARLIER感到害怕,因?yàn)樗麄儧](méi)有考慮行上下文亏吝,岭埠,也沒(méi)有考慮到可以通過(guò)在同一個(gè)表上創(chuàng)建多個(gè)迭代來(lái)嵌套行上下文。實(shí)際上蔚鸥,EARLIER是一個(gè)非常簡(jiǎn)單的功能惜论,可以多次使用。以下代碼最終解決了該方案:
Product[UnitPriceRank] =
COUNTROWS (
FILTER (
Product,
Product[UnitPrice] > EARLIER ( Product[UnitPrice] )
))
+ 1
在圖4-8中止喷,您可以看到Product表中定義的計(jì)算列馆类,該列已使用Unit Price按降序排序
因?yàn)橛?4種產(chǎn)品單價(jià)相同启盛,所以他們的排名總是1蹦掐;第15個(gè)產(chǎn)品的排名為15,與其他同等價(jià)格的產(chǎn)品齊名僵闯。我們建議您仔細(xì)研究并理解這個(gè)小示例,因?yàn)檫@是一個(gè)非常好的測(cè)試藤滥,可以檢查您使用和理解行上下文的能力鳖粟,以及如何使用迭代器(在本例中是FILTER)創(chuàng)建它們,以及如何通過(guò)EARLIER的使用訪問(wèn)它們之外的值拙绊。
備注:
EARLIER接受第二個(gè)參數(shù)向图,即跳過(guò)的步驟數(shù)泳秀,以便您可以跳過(guò)兩個(gè)或更多行上下文。此外榄攀,還有一個(gè)名為EARLIEST的函數(shù)嗜傅,它允許您直接訪問(wèn)為表定義的最外層的行上下文。老實(shí)說(shuō)檩赢,EARLIER的第二個(gè)參數(shù)和EARLIEST都不經(jīng)常使用:雖然有兩個(gè)嵌套的行上下文是一個(gè)常見(jiàn)的場(chǎng)景吕嘀,但是有三個(gè)或更多的行上下文是很少發(fā)生的事情。
在結(jié)束這個(gè)例子之前贞瞒,值得注意的是偶房,如果您想將這個(gè)值轉(zhuǎn)換為一個(gè)更好的排名(即,一個(gè)值從1開(kāi)始军浆,然后增長(zhǎng)為1棕洋,創(chuàng)建一個(gè)序列1,2,3…),那么計(jì)算價(jià)格而不是計(jì)算產(chǎn)品就足夠了乒融。在這里掰盘,您在上一章中學(xué)到的VALUES函數(shù)可以幫助您:
Product[UnitPriceRankDense] =
COUNTROWS (
FILTER (
VALUES ( Product[UnitPrice] ),
Product[UnitPrice] > EARLIER ( Product[UnitPrice] )
))
+ 1
我們強(qiáng)烈建議您學(xué)習(xí)并徹底理解EARLIER,因?yàn)槟鷷?huì)經(jīng)常使用它碟摆。盡管如此晃财,重要的是要注意,可以在許多場(chǎng)景中使用變量來(lái)避免EARLIER的使用典蜕。此外断盛,仔細(xì)使用變量使代碼更容易閱讀。例如愉舔,您可以使用以下表達(dá)式計(jì)算先前計(jì)算的列:
Product[UnitPriceRankDense] =
VAR
CurrentPrice = Product[UnitPrice]
RETURN
COUNTROWS (
FILTER (
VALUES ( Product[UnitPrice] ),
Product[UnitPrice] > CurrentPrice
))
+ 1
在最后一個(gè)示例中钢猛,使用變量,將當(dāng)前單位價(jià)格存儲(chǔ)在CurrentPrice變量中轩缤,稍后您將使用該變量執(zhí)行比較命迈。給變量命名,可以使代碼更容易閱讀火的,而無(wú)需每次讀取表達(dá)式時(shí)都遍歷行上下文堆棧來(lái)理解計(jì)算流程壶愤。
4.4 理解FILTER、ALL和上下文轉(zhuǎn)換
在前面的示例中馏鹤,我們使用FILTER作為篩選表的一種方便方法征椒。FILTER是一個(gè)非常常用的函數(shù),當(dāng)您想應(yīng)用一個(gè)篩選器來(lái)進(jìn)一步限制現(xiàn)有上下文時(shí)湃累,可以使用它勃救。
假設(shè)您想創(chuàng)建一個(gè)計(jì)算紅色產(chǎn)品數(shù)量的度量值碍讨。根據(jù)你目前所學(xué)的知識(shí),這個(gè)公式很簡(jiǎn)單:
[NumOfRedProducts] :=
COUNTROWS (
FILTER (
Product,
Product[Color] = "Red"
))
這個(gè)公式工作正常蒙秒,您可以在數(shù)據(jù)透視表中使用它勃黍;例如,將品牌放在行上以生成如圖4-10所示的報(bào)告晕讲。
在繼續(xù)這個(gè)例子之前,停下片刻并仔細(xì)考慮DAX如何計(jì)算這些值是很有用的益兄。品牌是Product表的一列锻梳。引擎在行中的品牌定義的上下文中計(jì)算每個(gè)單元格的NumOfRedProducts。因此净捅,每個(gè)單元格顯示具有由相應(yīng)行指定的品牌的紅色產(chǎn)品的數(shù)量疑枯。之所以會(huì)發(fā)生這種情況,是因?yàn)楫?dāng)您要求迭代Product表時(shí)蛔六,實(shí)際上是在要求迭代當(dāng)前篩選上下文中是可見(jiàn)的Product表荆永,其中只包含特定品牌的產(chǎn)品。這可能看起來(lái)微不足道国章,但最好還是記住它而不是忘記它具钥。
如果在包含顏色的工作表上放置切片器,則更明顯液兽。在圖4-11中骂删,我們創(chuàng)建了兩個(gè)相同的數(shù)據(jù)透視表,其中切片器為彩色四啰。您可以看到左側(cè)的顏色為紅色宁玫,并且數(shù)字與圖4-10中的相同,而在右側(cè)柑晒,數(shù)據(jù)透視表為空欧瘪,因?yàn)榍衅鞯念伾珵榫G色。
在右側(cè)數(shù)據(jù)透視表中佛掖,傳遞給FILTER的Product表僅包含Green產(chǎn)品,并且由于沒(méi)有產(chǎn)品可以同時(shí)為紅色和綠色涌庭,因此它總是計(jì)算為BLANK(即芥被,F(xiàn)ILTER不會(huì)返回任何行給COUNTROWS)。
這個(gè)例子的重要部分是脾猛,在同一個(gè)公式中撕彤,有一個(gè)來(lái)自外部的篩選上下文(由切片器選擇影響的數(shù)據(jù)透視表單元格)和公式中引入的行上下文。
兩個(gè)上下文同時(shí)工作并修改公式結(jié)果猛拴。 DAX使用篩選器上下文來(lái)計(jì)算Product表羹铅,并使用行上下文在迭代期間篩選行。
此時(shí)愉昆,您可能希望定義另一個(gè)公式职员,該公式返回紅色產(chǎn)品的數(shù)量,而不管在切片器上進(jìn)行的選擇跛溉。因此焊切,您希望忽略在切片器上進(jìn)行的選擇,并始終返回紅色產(chǎn)品的數(shù)量芳室。
您可以使用ALL函數(shù)輕松完成此操作专肪。 ALL返回表的內(nèi)容,忽略篩選上下文堪侯,也就是說(shuō)嚎尤,它總是返回表的所有行。您可以使用以下表達(dá)式定義名為NumOfAllRedProducts的新度量值:
[NumOfAllRedProducts] :=
COUNTROWS (
FILTER (
ALL ( Product ),
Product[Color] = "Red"
))
這一次伍宦,我們使用ALL(Product),而不是僅引用Product,這意味著我們要忽略現(xiàn)有的篩選上下文并始終遍歷所有產(chǎn)品缰冤。結(jié)果絕對(duì)不是我們所期望的辛萍,如圖4-12所示。
!圖4-12 NumOfAllRedProducts返回奇怪的結(jié)果卖毁。](https://upload-images.jianshu.io/upload_images/14379683-2af9c62d0f6635e8.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
這里有幾個(gè)有趣的事情要注意:
- 結(jié)果總是99揖曾,無(wú)論行上選擇的品牌如何。
- 左透視表中的品牌與右透視表中的品牌不同亥啦。
讓我們研究這兩個(gè)主題炭剪。首先,99是數(shù)據(jù)庫(kù)中紅色產(chǎn)品的總數(shù)禁悠。使用ALL后念祭,我們已從Product表中刪除了所有篩選器,也就是說(shuō)碍侦,我們已刪除了顏色篩選器和品牌篩選器粱坤。這是一個(gè)不想要的效果,但不幸的是瓷产,在目前對(duì)DAX的有限知識(shí)下站玄,我們沒(méi)有任何其他選擇。 ALL非常強(qiáng)大濒旦,但它是一個(gè)全有或全無(wú)的函數(shù):如果使用它株旷,它會(huì)刪除所有篩選器;它沒(méi)有選擇只刪除其中的一部分。更具體地說(shuō)晾剖,我們希望僅刪除顏色上的篩選器锉矢,而不改變所有其他篩選器。在下一章中齿尽,您將學(xué)習(xí)如何通過(guò)使用CALCULATE來(lái)解決此問(wèn)題沽损。
第二點(diǎn)更容易理解:因?yàn)槲覀冞x擇了Green,我們看到的是綠色產(chǎn)品的制造商循头,而不是所有產(chǎn)品的制造商绵估。因此,最右邊的數(shù)據(jù)透視表顯示了綠色產(chǎn)品制造商在數(shù)據(jù)庫(kù)中的紅色產(chǎn)品總數(shù)卡骂。這是因?yàn)橛糜谔畛鋽?shù)據(jù)透視表行的制造商列表是在原始篩選器上下文中計(jì)算的国裳,其中包含顏色等于綠色的篩選器。計(jì)算完行后全跨,計(jì)算出值缝左,結(jié)果總是返回99。
備注:
DAX的這種行為稱為“AutoExists邏輯螟蒸『惺梗”它看起來(lái)非常自然,因?yàn)樗[藏了不存在的值七嫌,盡管有一些內(nèi)部復(fù)雜性少办。在第10章“高級(jí)計(jì)算上下文”中,我們將專門用一節(jié)來(lái)詳細(xì)描述AutoExists行為诵原。
我們現(xiàn)在不想解決這個(gè)問(wèn)題英妓。稍后,當(dāng)您學(xué)習(xí)CALCULATE時(shí)绍赛,您將獲得解決方案蔓纠,它具有特定的功能來(lái)解決這類問(wèn)題。到目前為止吗蚌,我們已經(jīng)使用這個(gè)例子來(lái)說(shuō)明腿倚,在同一個(gè)表達(dá)式中,由于上下文共存及相互作用蚯妇,您可能會(huì)發(fā)現(xiàn)一個(gè)相對(duì)簡(jiǎn)單的公式返回奇怪結(jié)果敷燎。
4.5 使用許多表
我們剛剛開(kāi)始學(xué)習(xí)上下文,到目前為止箩言,這讓我們得到了一些有趣(和令人驚訝)的結(jié)果硬贯。您可能已經(jīng)注意到我們故意只使用一個(gè)表:Product。只有一個(gè)表陨收,您只需面對(duì)同一表達(dá)式中行上下文和篩選上下文之間的交互饭豹。
很少有數(shù)據(jù)模型只包含一個(gè)表。在您的數(shù)據(jù)模型中,很可能有許多表通過(guò)關(guān)系連接拄衰。因此它褪,一個(gè)有趣的問(wèn)題是“兩種上下文如何在關(guān)系中作用?”而且肾砂,由于關(guān)系有一個(gè)方向列赎,我們需要了解在關(guān)系的一端和多段發(fā)生了什么宏悦。最后镐确,為了使事情變得更加困難,請(qǐng)回想一下饼煞,關(guān)系可以是單向的源葫,也可以是雙向的,具體取決于您如何定義關(guān)系本身的交叉篩選器方向砖瞧。
如果在關(guān)系的多端的表上創(chuàng)建行上下文息堂,您是否希望它允許您使用一端的列?此外块促,如果您在關(guān)系的一端創(chuàng)建行上下文荣堰,您是否希望能夠訪問(wèn)多端的表中的列?另外竭翠,篩選上下文怎么樣振坚?你是否希望在多端表上放置一個(gè)篩選器并將其傳遞到一端的表中?任何答案都可能是正確的斋扰,但我們有興趣學(xué)習(xí)DAX在這些情況下的行為渡八,即理解DAX語(yǔ)言如何通過(guò)關(guān)系定義上下文的傳遞。正如您將要學(xué)習(xí)的那樣传货,上下文和關(guān)系之間存在一些微妙的相互作用屎鳍,學(xué)習(xí)它們需要一些耐心。
為了研究這個(gè)場(chǎng)景问裕,我們使用了一個(gè)包含6個(gè)表的數(shù)據(jù)模型逮壁,如圖4-13所示。
關(guān)于這個(gè)模型有幾點(diǎn)需要注意:
- 從銷售到產(chǎn)品類別,通過(guò)產(chǎn)品和產(chǎn)品子類別窟勃,有一對(duì)一對(duì)多的關(guān)系鏈祖乳。
- 唯一的雙向關(guān)系是銷售和產(chǎn)品之間的關(guān)系。所有剩余的關(guān)系都設(shè)置為單向交叉濾波方向秉氧。
現(xiàn)在我們已經(jīng)定義了模型眷昆,讓我們通過(guò)查看一些DAX公式來(lái)開(kāi)始查看上下文的行為。
4.5.1 行上下文和關(guān)系
行上下文和關(guān)系的交互非常容易理解,因?yàn)闆](méi)有什么需要理解的:它們不會(huì)以任何方式交互亚斋,至少不會(huì)自動(dòng)交互作媚。
想象一下,您想在Sales表中創(chuàng)建一個(gè)計(jì)算列帅刊,其中包含存儲(chǔ)在事實(shí)表中的單價(jià)與Product表中存儲(chǔ)的產(chǎn)品清單價(jià)格之間的差異纸泡。你可以嘗試這個(gè)公式:
Sales[UnitPriceVariance] = Sales[UnitPrice] - Product[UnitPrice]
此表達(dá)式使用來(lái)自兩個(gè)不同表的兩列,DAX僅在Sales上迭代的行上下文中計(jì)算赖瞒,因?yàn)槟谠摫恚⊿ales)中定義了計(jì)算列女揭。Product在與Sales關(guān)系的一端,因此您可能希望能夠訪問(wèn)相關(guān)行(售出產(chǎn)品)的單價(jià)栏饮。不幸的是吧兔,這不會(huì)發(fā)生。 Sales中的行上下文不會(huì)自動(dòng)傳遞到Product袍嬉,如果您嘗試使用上面的公式創(chuàng)建計(jì)算列境蔼,則DAX會(huì)返回錯(cuò)誤。
如果要從關(guān)系多端的表中訪問(wèn)關(guān)系一端的列(如本示例中的情況)伺通,則必須使用RELATED函數(shù)箍土。 RELATED接受列名作為參數(shù),并從當(dāng)前行上下文開(kāi)始罐监,通過(guò)遵循多對(duì)一方向中的一個(gè)或多個(gè)關(guān)系找到對(duì)應(yīng)行中的列的值吴藻。
您可以使用以下代碼更正上面的公式:
Sales[UnitPriceVariance] = Sales[UnitPrice] - RELATED (Product[UnitPrice] )
當(dāng)您在關(guān)系的多端的表上有行上下文時(shí),RELATED有效笑诅。如果行上下文處于關(guān)系的一端调缨,則您無(wú)法使用它,因?yàn)樵谕ㄟ^(guò)關(guān)系可能會(huì)檢測(cè)到許多行吆你。在這種情況下弦叶,您需要使用RELATEDTABLE,它是RELATED的伴侶妇多。您可以在關(guān)系的一端使用RELATEDTABLE伤哺,它將返回與當(dāng)前行關(guān)聯(lián)的所有行(在多端的表中)。例如者祖,如果要計(jì)算每個(gè)產(chǎn)品的銷售數(shù)量立莉,可以使用以下公式,在Product上定義一個(gè)計(jì)算列:
Product[NumberOfSales] = COUNTROWS ( RELATEDTABLE ( Sales ) )
此表達(dá)式計(jì)算Sales表中與當(dāng)前產(chǎn)品對(duì)應(yīng)的行數(shù)七问。您可以在圖4-14中看到結(jié)果蜓耻。
值得注意的是刹淌,RELATED和RELATEDTABLE都可以遍歷一長(zhǎng)串關(guān)系來(lái)收集他們的結(jié)果饶氏;它們不限于單個(gè)關(guān)系。例如有勾,您可以使用與之前相同的代碼創(chuàng)建列疹启,但這次是在Product Category表中:
'Product Category'[NumberOfSales] = COUNTROWS ( RELATEDTABLE (
Sales ) )
結(jié)果是該類別的銷售數(shù)量,該類別遍歷從Product Category到Product Category蔼卡,然后到Product喊崖,最終到達(dá)Sales表的關(guān)系鏈。
備注:
RELATED和RELATEDTABLE的一般規(guī)則的唯一例外是一對(duì)一的關(guān)系雇逞。如果兩個(gè)表共享1:1的關(guān)系荤懂,那么您可以在兩個(gè)表中同時(shí)使用RELATED和RELATEDTABLE,結(jié)果將得到列值或具有單行的表喝峦,這取決于您使用的函數(shù)势誊。
關(guān)于關(guān)系鏈的唯一限制是所有關(guān)系需要是相同類型(即,一對(duì)多或多對(duì)一)谣蠢,并且所有關(guān)系都朝著相同的方向。如果你有兩個(gè)表通過(guò)一對(duì)多和多對(duì)一連接查近,中間有一個(gè)橋表眉踱,那么RELATED和RELATEDTABLE都不會(huì)起作用。 1:1關(guān)系同時(shí)表現(xiàn)為一對(duì)多和多對(duì)一霜威。因此谈喳,您可以在一對(duì)多的關(guān)系鏈中建立1:1的關(guān)系,而不會(huì)中斷戈泼。
讓我們用一個(gè)例子來(lái)說(shuō)明這個(gè)概念婿禽。您可能認(rèn)為客戶與產(chǎn)品相關(guān),因?yàn)榭蛻襞c銷售之間存在一對(duì)多關(guān)系大猛,而銷售與產(chǎn)品之間存在多對(duì)一關(guān)系扭倾。因此,一個(gè)關(guān)系鏈將兩個(gè)表連接起來(lái)挽绩。然而膛壹,這兩種關(guān)系并不在同一個(gè)方向上。
我們將此場(chǎng)景稱為多對(duì)多關(guān)系唉堪。換句話說(shuō)模聋,客戶與許多產(chǎn)品(購(gòu)買的產(chǎn)品)有關(guān),而產(chǎn)品與許多客戶(購(gòu)買產(chǎn)品的客戶)有關(guān)唠亚。稍后您將學(xué)習(xí)如何使多對(duì)多關(guān)系工作的細(xì)節(jié)链方;現(xiàn)在讓我們關(guān)注行上下文。如果您嘗試在多對(duì)多關(guān)系中應(yīng)用RELATEDTABLE灶搜,結(jié)果可能不是您所期望的祟蚀。例如共啃,考慮在Product中創(chuàng)建計(jì)算列的一個(gè)公式:
Product[NumOfBuyingCustomers] = COUNTROWS ( RELATEDTABLE (
Customer ) )
對(duì)于每一行,您可能希望看到購(gòu)買該產(chǎn)品的客戶數(shù)量暂题。出乎意料的是移剪,結(jié)果將始終是18869,即數(shù)據(jù)庫(kù)中的客戶總數(shù)薪者,如圖4-15所示纵苛。
RELATEDTABLE不能遵循關(guān)系鏈攻人,因?yàn)樗鼈兊姆较虿煌阂粋€(gè)是一對(duì)多,另一個(gè)是多對(duì)一悬槽。因此怀吻,Product的篩選器無(wú)法到達(dá)客戶。值得注意的是初婆,如果您在相反的方向嘗試這個(gè)公式蓬坡,也就是說(shuō),您計(jì)算每個(gè)客戶購(gòu)買的產(chǎn)品數(shù)量磅叛,結(jié)果將是正確的:代表客戶購(gòu)買的產(chǎn)品數(shù)量的每一行都有不同的數(shù)字屑咳。這種行為的原因不是篩選上下文的傳遞,而是由RELATEDTABLE中隱藏的計(jì)算創(chuàng)建的上下文轉(zhuǎn)換弊琴。為了完整起見(jiàn)兆龙,我們添加了最后一個(gè)注釋。現(xiàn)在還不是詳細(xì)說(shuō)明這一點(diǎn)的時(shí)候:在閱讀第5章“理解CALCULATE和CALCULATETABLE”之后敲董,您將更好地理解這一點(diǎn)紫皇。
4.5.2 篩選上下文和關(guān)系
您已經(jīng)了解到行上下文不與關(guān)系交互,并且如果要遍歷關(guān)系腋寨,則可以使用兩種不同的函數(shù)聪铺,具體取決于訪問(wèn)目標(biāo)表時(shí)您所處的關(guān)系的哪一端。
篩選上下文的行為方式不同:它們以自動(dòng)方式與關(guān)系交互精置,并且根據(jù)您設(shè)置關(guān)系篩選的方式计寇,它們具有不同的行為。一般規(guī)則是脂倦,如果在關(guān)系本身上設(shè)置的篩選方向使傳遞可行踱稍,則篩選上下文通過(guò)關(guān)系傳遞硫狞。
通過(guò)使用帶有幾個(gè)度量值的簡(jiǎn)單數(shù)據(jù)透視表,可以很容易地理解這種行為。在圖4-16中润讥,您可以看到一個(gè)數(shù)據(jù)透視表庇绽,瀏覽我們目前使用的數(shù)據(jù)模型衷畦,其中定義了三個(gè)非常簡(jiǎn)單的度量值,如下所示
[NumOfSales] := COUNTROWS ( Sales )
[NumOfProducts] := COUNTROWS ( Product )
[NumOfCustomers] := COUNTROWS ( Customer )
篩選器在產(chǎn)品顏色上赶盔。Product是與Sales之間一對(duì)多關(guān)系的一端企锌,因此篩選下文從Product傳播到Sales,您可以看到這一點(diǎn)于未,因?yàn)镹umOfSales度量值僅計(jì)算具有特定顏色的產(chǎn)品的銷售額撕攒。 NumOfProducts顯示每種顏色的產(chǎn)品數(shù)量,每行(顏色)的不同值是您所期望的烘浦,因?yàn)楹Y選器位于我們計(jì)算的同一個(gè)表中抖坪。
另一方面,計(jì)算客戶數(shù)量的NumOfCustomers總是顯示相同的值闷叉,即客戶總數(shù)擦俐。這是因?yàn)镃ustomer和Sales之間的關(guān)系,如圖4-17所示握侧,在Sales方向上有一個(gè)箭頭蚯瞧。
篩選器從Product開(kāi)始藕咏,然后傳遞到Sales(按照從Product到Sales的箭頭状知,已啟用)但是,當(dāng)它嘗試傳遞到Customer時(shí)孽查,它沒(méi)有找到讓它繼續(xù)的箭頭。因此坦喘,它停了下來(lái)盲再。單向關(guān)系允許在單個(gè)方向上傳遞篩選上下文,而不是兩者瓣铣。
你可以認(rèn)為關(guān)系上的箭頭就像信號(hào)燈答朋。如果它們被啟用,則信號(hào)燈亮綠色并且傳遞發(fā)生棠笑。另一方面梦碗,如果未啟用箭頭,則信號(hào)燈亮紅燈并且不能傳遞篩選器蓖救。
始終從任何關(guān)系的一端到多端啟用箭頭洪规。您可以選擇從多端到一端啟用它。如果讓箭頭禁用循捺,那么傳遞將不會(huì)從多端到一端斩例。
如果查看圖4-18中所示的數(shù)據(jù)透視表,可以更好地理解該行為从橘。這次我們不是在行上使用產(chǎn)品顏色念赶,而是按客戶教育進(jìn)行分類础钠。
這次篩選器從Customer開(kāi)始旗吁。它可以到達(dá)Sales表,因?yàn)樵趯?duì)應(yīng)關(guān)系中啟用了箭頭停局。然后很钓,從Sales,它可以進(jìn)一步傳遞到Product翻具,因?yàn)镾ales和Product之間的關(guān)系是雙向的履怯。
現(xiàn)在,您向模型添加一個(gè)類似的度量值裆泳,計(jì)算子類別的數(shù)量叹洲,例如以下一個(gè):
NumOfSubcategories := COUNTROWS ( 'Product Subcategory' )
將其添加到報(bào)告中,您將看到客戶教育未過(guò)濾子類別的數(shù)量工禾,如圖4-19所示运提。
這是因?yàn)镻roduct和Product Subcategory之間的關(guān)系是單向的民泵,即它允許篩選器在單個(gè)方向上傳播。一旦啟用從Product開(kāi)始的箭頭并轉(zhuǎn)到Product子類別槽畔,您將看到篩選器傳遞栈妆,如圖420所示。
正如行上下文所發(fā)生的那樣,要遍歷表格需要遍歷多少步驟并不重要:只要有一個(gè)啟用了的關(guān)系鏈早直,就會(huì)發(fā)生自動(dòng)傳播寥假。例如,如果在Product Category上放置篩選器霞扬,則篩選器將傳遞到Product Subcategory糕韧,然后傳遞到Product,最后傳遞到Sales喻圃。
重要的是要注意萤彩,在篩選上下文中沒(méi)有函數(shù)可以根據(jù)關(guān)系鏈從表中獲取列或值,因?yàn)楹Y選上下文在DAX表達(dá)式中的傳遞是自動(dòng)發(fā)生的级及,而行上下文的傳遞則不是乒疏,并且需要使用RELATED和RELATEDTABLE指定傳遞。
4.5.3 VALUES函數(shù)介紹
前面的示例非常有趣饮焦,因?yàn)樗@示了如何使用篩選方向計(jì)算購(gòu)買產(chǎn)品的客戶數(shù)量怕吴。然而窍侧,如果您只對(duì)計(jì)算客戶數(shù)量感興趣,那么還有一個(gè)有趣的替代方法转绷,我們將借此機(jī)會(huì)介紹另一個(gè)強(qiáng)大的函數(shù):VALUES伟件。
VALUES是一個(gè)表函數(shù),它只返回一列的表议经,包含當(dāng)前篩選上下文中可見(jiàn)的列的所有值斧账。VALUES有許多高級(jí)用途,稍后我們將介紹煞肾。到目前為止咧织,開(kāi)始使用VALUES只是為了更好地熟悉它的行為。
在上一個(gè)數(shù)據(jù)透視表中籍救,您可以使用以下DAX表達(dá)式修改NumOfCustomers的定義:
[NumOfCustomers] := COUNTROWS ( VALUES ( Sales[CustomerKey] )
)
此表達(dá)式不計(jì)算Customer表中的客戶數(shù)习绢。相反,它計(jì)算Sales中CustomerKey列在當(dāng)前篩選上下文中可見(jiàn)的值的數(shù)量蝙昙。因此闪萄,表達(dá)式不依賴于Sales和Customers之間的關(guān)系,它只使用Sales表奇颠。
當(dāng)您在Products上放置篩選器時(shí)败去,它也總是過(guò)濾Sales,因?yàn)楹Y選器從Product傳播到Sales烈拒。因此圆裕,并非所有CustomerKey的值都可見(jiàn),而是僅顯示與篩選產(chǎn)品的銷售相對(duì)應(yīng)的行中的值荆几。
表達(dá)式的含義是“計(jì)算與所選產(chǎn)品相關(guān)的銷售的客戶密鑰數(shù)量葫辐。”因?yàn)榭蛻裘荑€代表客戶伴郁,所以表達(dá)式有效地計(jì)算購(gòu)買這些產(chǎn)品的客戶數(shù)量。
備注:
您可以使用DISTINCTCOUNT獲得相同的結(jié)果蛋叼,DISTINCTCOUNT計(jì)算列的不同值的數(shù)量焊傅。作為一般規(guī)則,使用DISTINCTCOUNT比使用VALUES的COUNTROWS更好狈涮。在這里狐胎,我們使用COUNTROWS和VALUES是為了教育目的,因?yàn)閂ALUES是一個(gè)有用的函數(shù)歌馍,即使它最常見(jiàn)的用法將在后面的章節(jié)中詳細(xì)介紹握巢。
使用VALUES而不是利用關(guān)系的方向既有優(yōu)點(diǎn)也有缺點(diǎn)。當(dāng)然松却,在模型中設(shè)置篩選要靈活得多暴浦,因?yàn)樗褂昧岁P(guān)系溅话。因此,您不僅可以使用CustomerKey計(jì)算客戶歌焦,還可以計(jì)算客戶的任何其他屬性(例如飞几,客戶類別的數(shù)量)。話雖如此独撇,可能有一些原因迫使您使用單向篩選屑墨,或者出于性能原因可能需要使用VALUES。我們將在第12章“高級(jí)關(guān)系處理”中更詳細(xì)地討論這些主題纷铣。
4.5.4 介紹ISFILTERED卵史、ISCROSSFILTERED函數(shù)
有兩個(gè)函數(shù)非常有用,可以幫助您更好地理解篩選上下文的傳遞搜立。此外以躯,學(xué)習(xí)它們是介紹透視表計(jì)算中最有趣的概念之一的好方法,即檢測(cè)要從DAX中計(jì)算值的單元格儒拂。
這兩個(gè)函數(shù)旨在讓您檢測(cè)列的所有值是否在當(dāng)前篩選上下文中可見(jiàn)寸潦,它們是:
- ISFILTERED:返回TRUE或FALSE,這取決于作為參數(shù)傳遞的列上是否具有直接過(guò)濾器社痛,也就是說(shuō)见转,它已放在行、列蒜哀、切片器或篩選器上斩箫,并且正在對(duì)當(dāng)前單元格進(jìn)行篩選。
- ISCROSSFILTERED返回TRUE或FALSE撵儿,具體取決于列是否具有篩選器乘客,因?yàn)榱硪粋€(gè)篩選器的自動(dòng)傳遞,不僅因?yàn)樗厦嬗兄苯邮呛Y選器淀歇。
在本節(jié)中易核,我們感興趣的是使用這些函數(shù)來(lái)理解篩選上下文的傳遞。因此浪默,我們將創(chuàng)建虛擬表達(dá)式牡直,它們僅用作學(xué)習(xí)工具。
如果使用此定義創(chuàng)建新度量值:
[CategoryFilter] := ISFILTERED ( 'Product Category'[Category]
)
這個(gè)簡(jiǎn)單的度量返回應(yīng)用于產(chǎn)品類別名稱的ISFILTERED函數(shù)的值纳决。然后碰逸,您可以創(chuàng)建第二個(gè)度量值,該度量對(duì)產(chǎn)品顏色進(jìn)行相同的測(cè)試阔加。代碼是
[ColorFilter] := ISFILTERED ( Product[ColorName] )
如果將兩個(gè)度量值添加到數(shù)據(jù)透視表饵史,將類別放在切片器中,將顏色放在行上,結(jié)果將類似于圖4-21胳喷。
有趣的是牵辣,類別從未被篩選,因?yàn)榧词刮覀兲砑恿饲衅髋覀円矝](méi)有對(duì)其進(jìn)行選擇纬向。另一方面,顏色總是在行上進(jìn)行篩選戴卜,因?yàn)槊啃卸加刑囟ǖ念伾馓酰傆?jì)沒(méi)有,因?yàn)楹Y選上下文中不包含任何產(chǎn)品選擇投剥。
備注:
總計(jì)的這種行為师脂,也就是說(shuō),沒(méi)有行和列的篩選器江锨,當(dāng)你想修改公式以便于在總計(jì)級(jí)別上顯示一個(gè)不同值時(shí)吃警,這非常有用。實(shí)際上啄育,您將檢查是否對(duì)數(shù)據(jù)透視表報(bào)告中出現(xiàn)的屬性進(jìn)行了篩選酌心,以便了解所計(jì)算的單元格是位于數(shù)據(jù)透視表的內(nèi)部,還是位于總計(jì)級(jí)別挑豌。
如果現(xiàn)在從類別切片器中選擇一些值安券,則結(jié)果會(huì)更改。現(xiàn)在該類別總是有一個(gè)篩選器氓英,如圖4-22所示侯勉。實(shí)際上,切片器引入的篩選上下文即使在數(shù)據(jù)透視表的總計(jì)級(jí)別也是有效的铝阐。
ISFILTERED可用于檢測(cè)列上是否有直接篩選器。在某些情況下徘键,列不會(huì)顯示其所有值芳誓,不是因?yàn)槟诤Y選列,而是因?yàn)槟诹硪涣猩戏胖昧撕Y選器啊鸭。例如,如果您篩選顏色并查詢產(chǎn)品品牌的值匿值,那么您將僅得到該特定顏色的產(chǎn)品品牌赠制。當(dāng)一個(gè)列因?yàn)榱硪粋€(gè)列上的篩選器而被篩選時(shí),我們說(shuō)該列是交叉篩選的,并且ISCROSSFILTERED函數(shù)可以檢測(cè)到這一情況钟些。
如果將這兩個(gè)新度量值添加到要檢查的數(shù)據(jù)模型中烟号,這次是ISCROSSFILTERED的顏色和類別:
[CrossCategory] := ISCROSSFILTERED ( 'Product
Category'[Category] )
[CrossColor] := ISCROSSFILTERED ( Product[Color] )
然后您將看到如圖4-23所示的結(jié)果。
您可以看到顏色是交叉篩選而類別不是汪拥。此時(shí),一個(gè)有趣的問(wèn)題是“為什么類別未被篩選篙耗?”當(dāng)您過(guò)濾顏色時(shí)迫筑,您可能希望只看到特定顏色的產(chǎn)品類別。要回答這個(gè)問(wèn)題宗弯,您需要記住該類別不是Product表的列脯燃。相反,它是產(chǎn)品類別的一部分蒙保,關(guān)系上的箭頭不會(huì)讓關(guān)系傳遞辕棚。如果更改數(shù)據(jù)模型,啟用從產(chǎn)品到產(chǎn)品類別的完整關(guān)系鏈的雙向篩選邓厕,則結(jié)果將不同逝嚎,如圖4-24所示。
在本節(jié)中,您已經(jīng)看到了ISFILTERED和ISCROSSFILTERED的一些示例单雾,主要用于教育目的赚哗,因?yàn)槟鷥H使用它們來(lái)更好地理解篩選上下文如何通過(guò)關(guān)系傳遞。在接下來(lái)的章節(jié)中硅堆,通過(guò)編寫高級(jí)DAX代碼屿储,您將了解為什么這兩個(gè)函數(shù)如此有用。
4.6 計(jì)算上下文回顧
讓我們回顧一下我們?cè)谟?jì)算上下文中學(xué)到的所有知識(shí)渐逃。
- 計(jì)算上下文是通過(guò)篩選數(shù)據(jù)模型并在需要訪問(wèn)列值時(shí)提供當(dāng)前行概念來(lái)修改DAX表達(dá)式的值的上下文谎柄。
- 評(píng)估上下文由兩部分組成:行上下文和過(guò)濾器上下文。它們共存柳弄,它們存在于所有公式中抠蚣。為了理解公式的行為,您始終需要考慮這兩種上下文面殖,因?yàn)樗鼈兺瑫r(shí)起作用竖哩。
- 定義計(jì)算列時(shí),DAX會(huì)自動(dòng)創(chuàng)建行上下文脊僚。您還可以使用迭代器函數(shù)以編程方式創(chuàng)建行上下文相叁。所有迭代器都定義行上下文。
- 您可以嵌套行上下文,在這種情況下增淹,EARLIER函數(shù)可用于訪問(wèn)上一行上下文椿访。
- 在使用數(shù)據(jù)透視表時(shí),您可以通過(guò)使用行虑润、列成玫、切片器和篩選器上的字段來(lái)創(chuàng)建篩選上下文。有一種方法可以使用CALCULATE以編程方式創(chuàng)建篩選上下文拳喻,但我們還沒(méi)有學(xué)到它哭当。我們希望在這一點(diǎn)上你應(yīng)該非常好奇地了解它!
- 行上下文不會(huì)自動(dòng)通過(guò)關(guān)系傳遞舞蔽。通過(guò)使用RELATED和RELATEDTABLE手動(dòng)進(jìn)行傳遞荣病。您需要在一對(duì)多關(guān)系的正確使用這些函數(shù):在多端使用RELATED,在一端使用RELATEDTABLE渗柿。
- 篩選上下文隨篩選關(guān)系自動(dòng)傳遞个盆。它總是從關(guān)系的一端傳遞到多端。此外朵栖,您還可以選擇啟用從多端到一端的傳遞颊亮。沒(méi)有函數(shù)可用來(lái)強(qiáng)制傳遞:根據(jù)數(shù)據(jù)模型中關(guān)系的定義,引擎內(nèi)的所有事情都是自動(dòng)發(fā)生的陨溅。
+VALUES返回一個(gè)包含單列表的表终惑,該表包含當(dāng)前篩選上下文中可見(jiàn)的列的所有唯一值。您可以使用結(jié)果表作為任何迭代器的參數(shù)门扇。
至此雹有,您已經(jīng)學(xué)習(xí)了DAX語(yǔ)言中最復(fù)雜的概念主題。這些點(diǎn)控制了公式的所有計(jì)算流程臼寄,它們是DAX語(yǔ)言的支柱霸奕。當(dāng)你遇到一個(gè)表達(dá)式,它不按你想象的計(jì)算吉拳,很有可能是因?yàn)槟氵€沒(méi)有完全理解這些規(guī)則质帅。
正如我們?cè)谝灾兴f(shuō),在第一次閱讀時(shí)留攒,所有這些主題看起來(lái)都非常簡(jiǎn)單煤惩。事實(shí)上,他們是炼邀。使它們復(fù)雜的原因在于魄揉,在一個(gè)復(fù)雜表達(dá)式中,公式的不同部分可能有多個(gè)活動(dòng)的計(jì)算上下文拭宁。掌握計(jì)算上下文是您將通過(guò)經(jīng)驗(yàn)獲得的技能什猖,在下一章中票彪,我們將通過(guò)展示許多示例來(lái)幫助您。通過(guò)使用一些DAX公式不狮,您將直觀地知道使用了哪些上下文以及它們需要哪些函數(shù),并最終掌握DAX語(yǔ)言在旱。
4.6 創(chuàng)建參數(shù)表
在本章中摇零,您學(xué)習(xí)了許多關(guān)于計(jì)算上下文的理論概念。現(xiàn)在是時(shí)候使用它們中的一些知識(shí)來(lái)解決一個(gè)有趣的場(chǎng)景并學(xué)習(xí)一種非常有用的技術(shù)桶蝎,即使用參數(shù)表驻仅。
參數(shù)表的想法是創(chuàng)建一個(gè)與數(shù)據(jù)模型其余部分無(wú)關(guān)的表,但是您將在DAX表達(dá)式內(nèi)部使用它來(lái)修改公式的行為登渣。一個(gè)例子可能有助于說(shuō)明這一點(diǎn)噪服。想象一下,您創(chuàng)建了一個(gè)顯示銷售額總和的報(bào)告胜茧,并且由于您的公司銷售的商品很多粘优,因此報(bào)告中顯示的數(shù)字非常大。因?yàn)槲覀兊氖纠龜?shù)據(jù)庫(kù)沒(méi)有遇到此問(wèn)題呻顽,所以我們創(chuàng)建了一個(gè)度量值雹顺,它對(duì)SalesAmount的立方求和,而不是使用SalesAmount列廊遍,因此數(shù)字更大嬉愧,所描述的場(chǎng)景更加真實(shí)。在圖4-25中喉前,您可以看到此報(bào)告没酣。
這份報(bào)告的問(wèn)題是數(shù)字很大卵迂,而且往往難以閱讀裕便。它們是數(shù)百萬(wàn)、數(shù)十億還是數(shù)萬(wàn)億狭握?而且闪金,他們?cè)趫?bào)告中占用了大量空間,沒(méi)有攜帶太多信息论颅。對(duì)于這種報(bào)告哎垦,一個(gè)常見(jiàn)的要求是使用不同的比例顯示數(shù)字。例如恃疯,您可能希望顯示除??以千或百萬(wàn)的值漏设,以便它們得到更小的數(shù)字,同時(shí)仍然攜帶有用的信息今妄。
您可以通過(guò)修改度量值并將其除以千來(lái)輕松解決此問(wèn)題郑口。唯一的問(wèn)題是鸳碧,根據(jù)數(shù)字的相對(duì)大小,您可能希望將它們視為真實(shí)值(如果它們足夠腥浴)瞻离,除以數(shù)千或除以數(shù)百萬(wàn)。此時(shí)創(chuàng)建三個(gè)度量值似乎很麻煩乒裆,我們希望找到一個(gè)更好的解決方案套利,無(wú)需創(chuàng)建多個(gè)不同的度量值。
我們的想法是讓用戶在使用切片器時(shí)決定在報(bào)告中應(yīng)用哪個(gè)比例鹤耍。在圖4-26中肉迫,您可以看到我們要構(gòu)建的報(bào)告示例。
報(bào)告的有趣之處在于,您不使用ShowValueAs切片器來(lái)篩選數(shù)據(jù)杆怕。相反族购,您將使用它來(lái)更改數(shù)字所使用的比例。當(dāng)用戶選擇Real Value時(shí)财著,將顯示實(shí)際數(shù)字联四。如果選擇了千位,則實(shí)際數(shù)字除以一千撑教,并以相同的度量值顯示朝墩,而無(wú)需數(shù)據(jù)透視表的布局。這同樣適用于數(shù)百萬(wàn)和數(shù)十億伟姐。
要?jiǎng)?chuàng)建此報(bào)告收苏,首先需要一個(gè)包含要在切片器上顯示的值的表。在我們的示例中愤兵,我們使用Excel表來(lái)存儲(chǔ)比尺鹿霸。在更專業(yè)的解決方案中,最好將表存儲(chǔ)在SQL數(shù)據(jù)庫(kù)中秆乳。在圖4-27中懦鼠,您可以看到此表的內(nèi)容。
顯然肛冶,您無(wú)法與該表創(chuàng)建任何關(guān)系,因?yàn)镾ales不包含任何可以用于與該表關(guān)聯(lián)的列扯键。不過(guò)睦袖,只要表在數(shù)據(jù)模型中,您就可以使用ShowValueAs列作為切片器的源荣刑。是的馅笙,你最終得到一個(gè)什么都不做的切片器伦乔,但是一些DAX代碼可以神奇地執(zhí)行閱讀用戶選擇并進(jìn)一步修改報(bào)告內(nèi)容。
您需要用于度量值的DAX表達(dá)式如下:
[ScaledSalesAmount] :=
IF (
HASONEVALUE ( Scale[DivideBy] ),
DIVIDE ( [Sales Amount], VALUES ( Scale[DivideBy] ) ),
[Sales Amount]
)
這個(gè)公式中有兩個(gè)值得注意的事項(xiàng):
- IF函數(shù)測(cè)試的條件是:HASONEVALUE(Scale [ShowValueAs])董习。此模式非常常見(jiàn):判斷Scale表的列是否只有一個(gè)值可見(jiàn)烈和。如果用戶沒(méi)有在切片器中選擇任何內(nèi)容,則列的所有值在當(dāng)前篩選上下文中都是可見(jiàn)的皿淋;也就是說(shuō)斥杜,HASONEVALUE將返回FALSE(因?yàn)樵摿兄杏性S多不同的值)。然后沥匈,如果用戶選擇了單個(gè)值,則只有那個(gè)值可見(jiàn)忘渔,HASONEVALUE將返回TRUE高帖。因此,條件讀作:“如果用戶為ShowValueAs屬性選擇了單個(gè)值畦粮∩⒅罚”
- 如果選擇了單個(gè)值,那么您就知道單個(gè)行是可見(jiàn)的宣赔。因此预麸,您可以計(jì)算VALUES(Scale [DivideBy]),并確保結(jié)果表只包含一列和一行(篩選下文中可見(jiàn)的一行)儒将。 DAX將VALUES返回的一行一列表轉(zhuǎn)換為標(biāo)量值吏祸。如果在結(jié)果是包含多行的表時(shí)嘗試使用VALUES讀取單個(gè)值,則返回一個(gè)錯(cuò)誤钩蚊。但是贡翘,在此特定方案中,您確定返回的值只有一個(gè)砰逻,因?yàn)镮F函數(shù)測(cè)試了前面的條件鸣驱。
因此,您可以將表達(dá)式讀作:“如果用戶在切片器中選擇了單個(gè)值蝠咆,則顯示銷售額除以相應(yīng)的分母踊东,否則顯示原始銷售額「詹伲”結(jié)果是一個(gè)可以交互式更改顯示值的報(bào)告闸翅,使用切片器就好像它是一個(gè)按鈕。顯然赡茸,由于報(bào)告僅使用標(biāo)準(zhǔn)DAX公式缎脾,因此當(dāng)部署到SharePoint或Power BI時(shí)也可以使用。
參數(shù)表在構(gòu)建報(bào)表時(shí)非常有用占卧。我們展示了一個(gè)非常簡(jiǎn)單(但十分常用)的例子遗菠,但唯一的限制是你的想象力联喘。您可以創(chuàng)建參數(shù)表來(lái)修改數(shù)字的計(jì)算方式,更改特定算法的參數(shù)辙纬,或執(zhí)行其他復(fù)雜操作以更改DAX代碼返回的值豁遭。