CALCULATE 庖丁解牛系列- CALCULATE專解(2)

CALCULATE之庖丁解牛系列 -- CALCULATE專解(2)

? ? ? 友情提示:108式并不是全部為理論,最后一半是定義DAX公式解決業(yè)務(wù)場(chǎng)景的話題胆描。

? ? ? 前面我們挺啰嗦地介紹了CALCUALTE構(gòu)成我們計(jì)算需要的最重要的元度量瘫想。今后幾乎所有的度量都將基于元度量為基礎(chǔ)進(jìn)行變化而來(lái)。
? ? ? 接著還介紹了隱式行篩選與顯式列表篩選的行為在計(jì)算列昌讲、度量情形下的使用国夜。通過(guò)學(xué)習(xí)兩個(gè)最基本的元度量,說(shuō)明你已經(jīng)可以寫出最初的兩個(gè)公式:

? ? ? [元度量_隱式]:= SUM(Sales[sale])
? ? ? [元度量_顯式]:= CALCULATE(SUM(Sales[sale]))

? ? ? ? 其實(shí)到這里短绸,是DAX的一個(gè)分水嶺车吹,即使是現(xiàn)在還只是創(chuàng)建元度量筹裕,但你也可以只運(yùn)用它就能解決大多數(shù)業(yè)務(wù)問(wèn)題了。雖然很基礎(chǔ)窄驹,讓我們摸擬一下DAX運(yùn)用的經(jīng)典三部曲:
? ? ? 第一步:將需要的數(shù)據(jù)加載到Powerpivot或PowerBI里朝卒,成為特定的某個(gè)業(yè)務(wù)數(shù)據(jù)模型(單元性或系統(tǒng)性,將根據(jù)模型的擴(kuò)展性而定)乐埠。當(dāng)然抗斤,有這些導(dǎo)入數(shù)據(jù)的入口選擇(可以導(dǎo)入幾乎任何類型的數(shù)據(jù)):

? ? ? 第二步:在模型表的計(jì)算區(qū)域(數(shù)據(jù)區(qū)域下方的空白單元格區(qū)域,也可以使用Excel的PowerPivot菜單下的新建度量)饮戳。創(chuàng)建需要的最簡(jiǎn)單的元度量豪治。這里,你可以直接選中某個(gè)需要計(jì)算的列:比如[銷售額]扯罐,然后選擇自動(dòng)匯總的方式(總和负拟、計(jì)數(shù)、平均值等)歹河,如圖:

? ? ? 結(jié)果會(huì)直接在該列的下方單元格里生成一個(gè)度量掩浙,如果對(duì)默認(rèn)的名稱不滿意,你可以修改它秸歧。

? ? ? ? 如果該表包含的列表厨姚,不能滿足你的計(jì)算(篩選列表等),那就需要簡(jiǎn)單的建模(其實(shí)就是拖拽列表連線列表間的關(guān)系)键菱,如圖:可參與計(jì)算的列表變得很多很多(例如老生常談的透視表里的行谬墙、列、切片器用到的維度列表经备,DAX計(jì)算式里的參數(shù)列表等)拭抬。

? ? ? ? 第三步:拖拽出一個(gè)透視表,針對(duì)該度量:[銷售額_的總和]侵蒙,給定一組列表篩選它造虎,或者運(yùn)用查詢輸出為鏈接回表……。以及其他的任何數(shù)據(jù)輸出纷闺。

? ? ? 故事當(dāng)然不會(huì)到此結(jié)束算凿。讓我們繼續(xù)前行?

? ? 第7式:CALCULATE中的過(guò)程與結(jié)果都是列表

? ? ? ? 無(wú)需質(zhì)疑:所有DAX數(shù)據(jù)模型都以列式存儲(chǔ)犁功,并以列式參與計(jì)算氓轰,并沒(méi)有行的概念。所有DAX(即CALCULATE)都是關(guān)于列表的浸卦。
? ? ? 這是由DAX內(nèi)部引擎原理決定的戒努。任何關(guān)于DAX的理解都需要回到該定義。這可以認(rèn)為是DAX中的一條語(yǔ)錄。別忙著否定它储玫,認(rèn)識(shí)它比否定它更讓你了解DAX。

? ? ? ? 那么萤皂,我們圍繞這句DAX語(yǔ)錄撒穷,總之是不會(huì)錯(cuò)的。讓我們一步一步來(lái)裆熙。

? ? ? 先說(shuō)下學(xué)習(xí)DAX中遇到的另一個(gè)問(wèn)題:(以下所說(shuō)的列表指代一個(gè)列或多個(gè)列端礼,多個(gè)組合在一起的屬性列表指代為表)。 由CALCULATE定義的DAX計(jì)算中操縱的永遠(yuǎn)是列表入录。依據(jù)是蛤奥,DAX存在于數(shù)據(jù)模型中,而數(shù)據(jù)模型里的數(shù)據(jù)是以列式存儲(chǔ)僚稿、列式執(zhí)行的凡桥。重要的東西需要不止說(shuō)三遍!

? ? ? 所以蚀同,DAX能識(shí)別的缅刽、能操作的永遠(yuǎn)只有列表(除非改變引擎存儲(chǔ)方式),我們前面提到的“顯式列表”概念也基于此蠢络。我們不是想把DAX的概念弄得“多多的復(fù)雜式”衰猛,而是“少少的簡(jiǎn)單式”。前提是有一個(gè)痛苦的啰嗦過(guò)程刹孔。
? ? ? 關(guān)于DAX(CALCULATE)的一切啡省,甚至最后只剩下兩個(gè)字:列表,或者最多四個(gè)字:列表+篩選髓霞。
? ? ? 為照顧到一些心急的讀者卦睹,我們先列舉個(gè)1、2酸茴、3分预、4⌒胶矗可能會(huì)一次性串燒到多個(gè)概念笼痹。

? ? ? ? 1、第一個(gè)問(wèn)題酪穿。其實(shí)是不得不說(shuō)的凳干、關(guān)于“當(dāng)前行”的問(wèn)題,也就是“行上下文”被济。這其實(shí)不是對(duì)錯(cuò)的問(wèn)題救赐,而是中西方語(yǔ)境差異的問(wèn)題,是最后沒(méi)有回到DAX內(nèi)部引擎的問(wèn)題……。它像是“美麗的謊言”经磅、難懂的“甲骨文”泌绣、“迷惑人的坑”,總之是“皇帝的新裝”预厌。注意阿迈,都是些帶引號(hào)的。

? ? (1)第一個(gè)問(wèn)題與DAX技術(shù)無(wú)關(guān)轧叽,是想問(wèn):行上下文究竟是個(gè)什么鬼苗沧?能明明白白的告訴我們么?
? ? ? 因?yàn)樽孕哦嗌賹?duì)語(yǔ)文里的上下文理解一點(diǎn)炭晒,如是百度了一下編程中提到的上下文是個(gè)什么樣子的待逞,還真是有大神的回答:

? ? ? ? 終于明白,編程的上下文指的就是:當(dāng)時(shí)計(jì)算所在的環(huán)境网严。對(duì)于DAX當(dāng)然是比較熟悉的:CALCULATE定義的行上下文和列表上下文所在的當(dāng)前計(jì)算環(huán)境识樱。如是,也有了:行上下文 =“當(dāng)前行”屿笼。
? ? ? 問(wèn)題是牺荠, DAX的函數(shù)語(yǔ)言要更強(qiáng)大一些馒闷,最終目的最好是變得像Excel的單元格一樣最好鸦致,寫一個(gè)函數(shù)公式牍鞠,不用考慮一丁點(diǎn)浆洗、一絲絲的編程絮宁,就知道這個(gè)函數(shù)公式能計(jì)算出正確的結(jié)果(這么多年我們都是這么干的窜觉。寫個(gè)Excel函數(shù)公式脱茉,我們也并沒(méi)有觀察過(guò)非驮、或者想過(guò)它的“當(dāng)前行”行為)胸懈。
? ? ? ? 現(xiàn)在可好担扑,搞個(gè)抽象的編程語(yǔ)言,這對(duì)于毫無(wú)編程經(jīng)驗(yàn)趣钱、手無(wú)寸鐵的非IT人員來(lái)說(shuō)涌献,也應(yīng)該是更不好理解。

? ? ? 你也許會(huì)說(shuō)首有,Excel與DAX是兩回事好不好燕垃。那好,我們就說(shuō)DAX:

? ? (2)就算是為了從編程語(yǔ)言上理解DAX的需要井联,可這還是有點(diǎn)“牛頭不對(duì)馬嘴”的味道卜壕?原諒我語(yǔ)氣太重,我是被“上下文”搞暈了這么多年烙常,已經(jīng)忍無(wú)可忍轴捎,忍無(wú)可忍那就無(wú)須再忍!哈哈。說(shuō)好的DAX注重業(yè)務(wù)邏輯(更像函數(shù)式語(yǔ)言)侦副,這可能會(huì)不算數(shù)侦锯?不能吧?

? ? (3)為了更官方一點(diǎn)(以便你相信我一次)秦驯,我只能請(qǐng)出大家還算信服的《DAX圣經(jīng)》的一句結(jié)論:VertiPaq (DAX工作的數(shù)據(jù)模型里的引擎)是一個(gè)列式數(shù)據(jù)庫(kù)率触。我們應(yīng)該拋棄表的思考方式轉(zhuǎn)而以列表的概念來(lái)理解它。
? ? ? 這應(yīng)該是很清楚汇竭、很明白的一句話了,我們稍微變動(dòng)一下穴张,也就是說(shuō)细燎,其實(shí) CALCULATE(DAX)的一切都是關(guān)于列表的。
? ? ? 這也是很多IT(搞編程的)人不一定學(xué)得好DAX的原因皂甘,因?yàn)樗麄兞?xí)慣于總用表的概念來(lái)理解和運(yùn)用DAX玻驻。
? ? ?
很顯然,DAX的數(shù)據(jù)模型里本沒(méi)有行偿枕,有的只是列表(哪怕只有一個(gè)數(shù)據(jù)行璧瞬,那也是列表),沒(méi)有行渐夸,哪來(lái)的行上下文嗤锉?它其實(shí)就是:皇帝的新裝,本來(lái)就沒(méi)有嘛墓塌!

? ? (4)問(wèn)題來(lái)了瘟忱,你先別急著罵我,我并沒(méi)有說(shuō)“行上下文”不好苫幢,而且現(xiàn)有的官方都采用這種方式來(lái)理解DAX访诱,用哪一個(gè)詞,并不重要韩肝,關(guān)鍵是能理解它触菜,運(yùn)用它就行。
? ? ? ? 感謝你耐著性子能看到這里哀峻,我是非官方涡相,我想很平靜的再接著聊一下為什么會(huì)使用“行篩選”而不是“行上下文”的原因。并不是想標(biāo)新立異谜诫、獨(dú)具一格漾峡。而是非得花多點(diǎn)文字才能搞清(即使暫時(shí)還不能太清晰,還需要后期的無(wú)數(shù)DAX案例檢驗(yàn))喻旷。

? ? ? 1)從字面上看生逸,有“行上下文”就對(duì)應(yīng)有“列表上下文”,前面已經(jīng)說(shuō)過(guò),這比較偏重于編程(寫DAX的槽袄、以及編輯學(xué)習(xí)DAX官方知識(shí)文檔的烙无,應(yīng)該也大都是IT編程人員),這其實(shí)還是表的概念遍尺,它太注重于表的運(yùn)行機(jī)制或者執(zhí)行方式(即定義表的計(jì)算環(huán)境:定義表的關(guān)系主鍵截酷、定義表的連接、定義查詢條件等等)乾戏。
? ? ? 但是迂苛,如果以DAX的列表概念來(lái)理解,那就簡(jiǎn)單得多鼓择。首先找到要計(jì)算的列表三幻,然后針對(duì)整列或該列的部分(列表篩選),最后可能需要按某個(gè)邏輯條件改變計(jì)算(行篩選)呐能。這就是我們說(shuō)的DAX的:篩選+計(jì)算念搬。

? ? ? 這時(shí)候,我們不需要過(guò)多的考慮那么多的定義摆出,也不需要太考慮列表關(guān)系:因?yàn)殛P(guān)系要不就是事先連接好的物理關(guān)系朗徊,只要不刪除它,它總是存在的偎漫,要不就是由公式定義的關(guān)系等等爷恳。
? ? ? 總習(xí)慣糾慮關(guān)系,這可能是:前期建模架構(gòu)不清晰骑丸、或?qū)ψ约旱臄?shù)據(jù)模型包含哪些內(nèi)容并不熟悉和不自信舌仍、亦或者是并不了解業(yè)務(wù)場(chǎng)景(對(duì)業(yè)務(wù)需要的度量、維度列表不熟)等等通危。所以铸豁,我們有:“業(yè)務(wù)邏輯高于分析工具本身"的說(shuō)法。

? ? ? 2)關(guān)鍵的一點(diǎn)菊碟,也是繞不開(kāi)的一點(diǎn)节芥。我們太熟悉和關(guān)心的“行的行為”--所謂的一行一行的找出來(lái),再一行一行的計(jì)算逆害,編程一點(diǎn)的說(shuō)法叫“遍歷”表头镊。
? ? ? 如是,我們給出了第一個(gè)“當(dāng)前篩選”的定義魄幕,即當(dāng)前列表計(jì)算環(huán)境的定義:“一組篩選器應(yīng)用到模型列表中相艇,從而改變整個(gè)數(shù)據(jù)列表集的當(dāng)前可見(jiàn)的行(列值)”。

? ? ? 即使這是一個(gè)正確的定義纯陨,但它仍然很幼稚坛芽。我相信很多希望學(xué)習(xí)DAX的人都不愿意停留在這里留储。可事實(shí)上咙轩,理解到這一步获讳,已經(jīng)能解決大多數(shù)的業(yè)務(wù)問(wèn)題了。
? ? ? 為了理解到更高一個(gè)層次活喊,需要記住前面的那句《DAX圣經(jīng)》里的話:
? ? ? 我們應(yīng)該拋棄表格的思考方式轉(zhuǎn)而以列表的概念來(lái)理解DAX丐膝,因?yàn)椋珻ALCULATE(DAX)的一切都是關(guān)于列表的钾菊。這是之前的一段理解(懶得打字帅矗,截圖如下):

? ? 數(shù)據(jù)模型里的表的樣子(常規(guī)表的樣子):

可是。我們更希望你將它想像成這個(gè)樣子(實(shí)際上也應(yīng)該是這個(gè)樣子):

? ? ? 我們還可以到數(shù)據(jù)模型關(guān)系視圖里體驗(yàn)一下:(為了節(jié)省截圖時(shí)間煞烫,采用一個(gè)原來(lái)使用過(guò)的圖示)损晤。

? ? ? ?這是我們創(chuàng)建的一個(gè)關(guān)系型物理列表的數(shù)據(jù)模型(關(guān)鍵的構(gòu)成要素是關(guān)系+列表),只要你不更新數(shù)據(jù)红竭,它總是一個(gè)最大的數(shù)據(jù)模型(即工作表模型)。它當(dāng)然包含所有計(jì)算需要的列表(更包括由它產(chǎn)生的列表—無(wú)論擴(kuò)展表喘落、新表茵宪、參數(shù)表等)。
? ? ? ?上圖的方式表明:表的正確表示將是一組列表(一個(gè)或多個(gè)單列表構(gòu)成瘦棋,并不考慮行-哪怕某個(gè)列只有一行稀火,某個(gè)列有干萬(wàn)行)。
? ? ? ?我們可能還記得:ExceI表格里沒(méi)有值的單元格通常會(huì)以0或空值代替赌朋,在數(shù)據(jù)模型里凰狞,引擎將為只有一行的列表自動(dòng)生成一個(gè)Null值來(lái)映射對(duì)應(yīng)另一個(gè)千萬(wàn)行的列的干萬(wàn)行-1的所有行。很顯然沛慢,對(duì)那個(gè)只有一行的列計(jì)數(shù)赡若,結(jié)果可能是2而不是1(當(dāng)然,你可定義非空值處理)团甲。在透視結(jié)果里所有Null值將篩選對(duì)應(yīng)的另一列的所有行計(jì)值逾冬,你知道這將是:空白值匯總。

? ? ? 如圖所示:NULL映射的行值對(duì)比躺苦。

? ? ? ?還有一個(gè)證明模型里單列表參與計(jì)算的位置身腻。我們?cè)贒AX公式編輯欄里隨便起個(gè)度量名,然后接一個(gè)英文的:= (計(jì)算列公式或PowerBl里只有 = )匹厘,這時(shí)候嘀趟,你只要輸入一個(gè) '(單引號(hào)),表示你要引用某個(gè)列表計(jì)算愈诚,智能提示會(huì)顯示出所有可能會(huì)用到的列表她按。這時(shí)候的列表牛隅,是你可以在數(shù)據(jù)摸型里引用的、真正的尤溜、全部顯式列表集倔叼。
? ? ? ?如果你想要引用的列表沒(méi)有出現(xiàn),那么宫莱,可能的原因:沒(méi)有這個(gè)物理列表(需要虛擬構(gòu)建)丈攒,或者還沒(méi)有建立關(guān)系(重建關(guān)系)。依此授霸,你還可以檢查某些公式定義的參數(shù)巡验,是否可以引用該列表(比如該位置沒(méi)有出現(xiàn)度量值列表,說(shuō)明該位置不能放置碘耳、引用度量等)显设。
? ? ? 而且,對(duì)于你更好的理解顯式的列表概念有幫助辛辨。在公式編輯欄里的智能提示中顯示的列表捕捂,你可以通過(guò)雙擊(直接引用的方式)放置在公式的適當(dāng)位置。如圖所示:

? ? ? ?這里值得提示一下:可引用的列表可能包括當(dāng)前公式中以VAR定義的變量斗搞,你可以使用RETURN函數(shù)將其取出指攒,并放置在公式合適的位置;之外僻焚,可能還包括已定義的度量值在內(nèi)允悦,這并不奇怪,度量是Calculate定義的結(jié)果虑啤,本身就是一個(gè)列表隙弛。
? ? ? ?你應(yīng)該還記得前面列舉的那個(gè)要顯式列表篩選才能正確計(jì)算的公式,我們使用度量名稱來(lái)替代CalcuIate(Sum(Sales[SaIe]))的顯式列表篩選狞山,也是可以的全闷。如果使用智能提示,你當(dāng)然可以在該位置直接雙擊引用該度量即可萍启。如圖左邊公式是錯(cuò)誤的室埋,而右邊的兩個(gè)(使用CALCULATE()顯式列表及度量列表是正確的):

? 更清楚一點(diǎn)的圖示:

? ? ? ?提示:其實(shí),你有沒(méi)有注意到伊约,我們每涉及到列表時(shí)姚淆,使用的都是“引用”一詞,而其他情況(比如行篩選屡律、值列表腌逢、變量)使用的都是“定義”一詞,“引用”的一般都是顯而易見(jiàn)的超埋、物理的搏讶、已存在的(顯式的)佳鳖,需要“定義”的(比如邏輯條件,那是隱式的媒惕、內(nèi)部的系吩、我們看不見(jiàn)的,對(duì)于DAX而言妒蔚,是那些需要引擎完成的部分穿挨。這就是中國(guó)漢字的奧妙。你不必糾結(jié)肴盏,略過(guò)這部分即可科盛。

? ? ? ?本來(lái)還想著提示一下列表的物化、虛擬概念菜皂,算了贞绵,已經(jīng)夠亂了。還是好好的研究一下DAX的使用說(shuō)明書吧恍飘。

? ? ? ?有點(diǎn)啰嗦了榨崩,接著說(shuō)列表。與普通Excel單元格區(qū)域表不同章母, DAX中的VertiPaq可理解為:是一個(gè)列式數(shù)據(jù)庫(kù)蜡饵。因此,所謂表的正確表示將是一個(gè)或多個(gè)(一組)列表(后面談到列表關(guān)系時(shí)胳施,將進(jìn)一步表述為一組關(guān)系列表,見(jiàn)上面的圖示)肢专。
? ? ? 將數(shù)據(jù)模型理解成一個(gè)個(gè)單列表組合在一起的樣子舞肆,這種可視化效果會(huì)更好些,而且對(duì)于后面理解另一個(gè)重要的單級(jí)關(guān)系連接的擴(kuò)展表概念有幫助(請(qǐng)參閱擴(kuò)展表系列)博杖,以及最后要說(shuō)的引擎的單線程(大多數(shù)情況下)執(zhí)行單個(gè)列表操作的特點(diǎn)(比如多個(gè)篩選不能同時(shí)作用于同一個(gè)列上)椿胯。

? ? ? ?DAX列表也與Excel、ACCESS剃根、SQL不同哩盲,在PowerPivot當(dāng)中,僅有一個(gè)全局性的數(shù)據(jù)集狈醉,稱為“數(shù)據(jù)模型”(PivotModel)廉油。一個(gè)Excel工作簿,有且只有一個(gè)數(shù)據(jù)模型(甚至沒(méi)有Powerpivot苗傅,它也能稱為一個(gè)數(shù)據(jù)模型)抒线。
? ? ? ?但是,大多數(shù)情況渣慕,我們用于計(jì)算的列表往往是模型列表的一個(gè)子集嘶炭,而且這個(gè)子集不一定來(lái)自同一個(gè)表(使用整個(gè)數(shù)據(jù)模型計(jì)算的情況很少抱慌,除非模型只有一個(gè)沒(méi)有關(guān)系的表)、也不一定是一個(gè)列的整列眨猎。這是我們學(xué)習(xí)DAX必須要明白的一個(gè)概念抑进。

? ? ? 因?yàn)椋覀冊(cè)趯慏AX時(shí)睡陪,可能是在某個(gè)表區(qū)域(該表所在計(jì)算區(qū)域里)寺渗,于是覺(jué)得DAX公式所在的數(shù)據(jù)模型就是這個(gè)表,這是不對(duì)的宝穗。你必須有一個(gè)全局性的關(guān)系型數(shù)據(jù)模型概念(請(qǐng)參閱擴(kuò)展表系列)户秤。
? ? ? 比如,你可以在任意一個(gè)表里(反正都是一個(gè)整體)寫公式逮矛,甚至可以將度量單獨(dú)放置在某個(gè)表里鸡号,并歸類管理。唯一需要注意的是须鼎,你需將公式里的列表顯式限定為表名稱+列表:表名稱[列表名]鲸伴。

? ? ? ?在平時(shí)運(yùn)用中,由于列表特性:你可以不用理會(huì)列表的位置(其實(shí)是不存在)晋控,由于沒(méi)有行的概念汞窗,你將很難處理諸如“行”的計(jì)算,以及對(duì)某列進(jìn)行真正意義上的內(nèi)部排序行為(雖然可以使用“按列排序”--請(qǐng)參閱《按列排序的坑》一文)赡译,甚至在具有粒度級(jí)別上的計(jì)算也是它的短板(這些需要通過(guò)技術(shù)性手段來(lái)處理)仲吏。
? ? ? ?我們暫時(shí)用:“事物總是有好有壞”的辯證法來(lái)總結(jié)它吧。

? ? 第8式:CALCULATE的篩選是一個(gè)或多個(gè)列表

? ? ? 我們終于可以更好的表述當(dāng)前列表篩選的定義:

? ? ? ?每個(gè)列表篩選是一組列表蝌焚,其中包含每一個(gè)單列表裹唆,并定義出該列的所有列值。而且只洒,在列表篩選中许帐,引擎始終認(rèn)為列表是可見(jiàn)的、存在的毕谴、顯式的成畦。所以,當(dāng)所有這些篩選器放入一個(gè)邏輯條件里時(shí)涝开,則形成當(dāng)前列表篩選循帐。
? ? ? ?例如:在一個(gè)透視表的單個(gè)單元中,都有來(lái)自切片器以及行舀武、列表篩選惧浴。每個(gè)篩選器都在列表、或定義的列表集合上操作奕剃。因此衷旅,在我們的實(shí)際DAX例子中捐腿,篩選都會(huì)包含一個(gè)或多個(gè)獨(dú)立的列表篩選,進(jìn)而篩選出計(jì)算列表(后面更進(jìn)一層的解釋是柿顶,每個(gè)單線程的單列表篩選匯總后再執(zhí)行篩選計(jì)算)茄袖。

? ? ? 綜上啰嗦,我們更好地理解了當(dāng)前列表篩選的含義嘁锯。唯一的問(wèn)題是宪祥,還是沒(méi)有對(duì)行的行為(行上下文)做出結(jié)論。有了前面的鋪墊家乘,應(yīng)該是時(shí)候來(lái)討論了蝗羊。
? ? ? 很多時(shí)候,僅僅元度量還是無(wú)法滿足業(yè)務(wù)建模需要的仁锯。元度量在粗獷的列表篩選中雖然也擁有列表組合篩選的變化耀找,但如果想要更新列表篩選(比如更改元度量的篩選),讓列表篩選在更細(xì)膩的某些邏輯條件下改變計(jì)算业崖,則需要為模型中的某些或全部到表篩選提供一個(gè)新的值列表野芒。DAX將用新的值列表替換該列上的列表篩選器,并以此方式生成一個(gè)新的列表篩選双炕。
? ? ? 你可以簡(jiǎn)單地狞悲、暫時(shí)地將這理解為:列表的列值(范圍)的變化。

? ? ? 這里第一次提到了"值列表"這個(gè)概念妇斤。它在DAX計(jì)算中也是一個(gè)繞不開(kāi)的關(guān)鍵話題摇锋。
? ? ? 首先,DAX引擎只接受顯式的列表站超。如是荸恕,你總是會(huì)在定義DAX公式時(shí),絕對(duì)離不開(kāi)思考如何用“列表篩選列表”(任何人都不例外顷编,而且這種能力并不是IT高手或引擎的發(fā)明者就厲害一些,就像造飛機(jī)的并不一定是駕駛飛機(jī)的剑刑、母雞下蛋并不需要知道蛋用來(lái)干什么去了媳纬,是一樣的道理)。
? ? ? ?無(wú)須質(zhì)疑施掏,這問(wèn)題總會(huì)讓人費(fèi)解與糾結(jié):
? ? ? ?什么是列表篩選列表钮惠?這樣能篩選嗎?
? ? ? ?這樣篩選對(duì)嗎七芭?這樣篩選的依據(jù)是什么素挽?
? ? ? ?這樣篩選的結(jié)果是什么?為什么同樣的列表篩選結(jié)果怎么不一樣了狸驳?等等预明。
? ? ? ?我們后面大部分的時(shí)間是用來(lái)研究這些問(wèn)題的(當(dāng)然缩赛,有時(shí)候這需要站在巨人的肩膀上)

? ? ? ?我們前面已提示過(guò),本系列知識(shí)可能比較跳躍撰糠。這里需要提前串燒一下DAX引擎的壓縮特征酥馍,以幫助我們理解上述幾個(gè)糾結(jié)不完的概念。內(nèi)部引擎是DAX的根與魂(雖然不要求理解內(nèi)部原理阅酪,但至少需要知道一點(diǎn)點(diǎn)大概的原理以及如何工作)旨袒,即先簡(jiǎn)單知道VertiPa引擎的以下兩點(diǎn)知識(shí):
? ? ?(1)VertiPa引擎有三大壓縮算法:值、字典术辐、行距壓縮(它會(huì)依列表類型自動(dòng)壓縮處理)砚尽;
? ? ?(2)DAX內(nèi)部三種引擎運(yùn)行的過(guò)程:壓縮引擎的VertiPaq壓縮-->存儲(chǔ)引擎的存儲(chǔ)數(shù)據(jù)(內(nèi)存里緩存)-->公式引擎的數(shù)據(jù)引用。其中公式引擎的典型運(yùn)算符包括:
? ? ? ? 1)列表之間的聯(lián)接(請(qǐng)參閱:聯(lián)接表系列)辉词;
? ? ? ? 2)具有復(fù)雜條件的篩選必孤、聚合和查詢等。 這些運(yùn)算符通常就是依據(jù)數(shù)據(jù)模型里的列表結(jié)構(gòu)(列表较屿、關(guān)系隧魄、列類型。再?zèng)]有其他了)隘蝎。

? ? ? ?為了講清列表的概念购啄,我們幾乎動(dòng)用了所有能動(dòng)用的資源(后面需要擴(kuò)展它們),你不需要一下子理解嘱么,知道有這回事就行狮含。
? ? ? ? 我們繼續(xù),先具體的談幾點(diǎn)能幫助我們理解的曼振、涉及引擎的那些:

? ? ?(1)決定列大屑钙(存儲(chǔ)與執(zhí)行消耗)的主要因素不是數(shù)據(jù)類型,也不是列值多少冰评,而是列的唯一值(基數(shù))的數(shù)量映胁。
? ? ? ? 因?yàn)椋瑑?nèi)部引擎會(huì)將重復(fù)的相同列值視為一個(gè)值處理甲雅,舉個(gè)例說(shuō)明:一個(gè)唯一值為3個(gè)值的50萬(wàn)行列值的列(引擎可能只需要處理3次)解孙,比一個(gè)唯一值為30個(gè)的只有500個(gè)行列值的列(引擎可能需要處理30次),在非常大的數(shù)據(jù)里將要快不只一個(gè)量級(jí)抛人。你如果習(xí)慣于理解為遍歷或迭代弛姜,那就是3次與30次的區(qū)別!
? ? ? ?我們能想到的是妖枚,引擎肯定是以列表來(lái)處理的廷臼,上面這個(gè)無(wú)論是否合適的舉例,也能確定引擎并不是一次性處理整列(1次,處理的不是一行荠商!)寂恬。
? ? ? ?假如說(shuō),引擎處理了3次结啼。那么掠剑,這個(gè)列表至少被引擎"四分五裂“過(guò)3次!無(wú)論中間的過(guò)程多么彎轉(zhuǎn)曲折(經(jīng)歷了多少個(gè)篩選郊愧、多少個(gè)邏輯條件限定朴译,比如那些看起來(lái)高大威猛的長(zhǎng)長(zhǎng)的DAX公式),目標(biāo)都是某個(gè)源數(shù)據(jù)模型里被定義用來(lái)計(jì)算的那個(gè)單列表(比如Calculate()的第一個(gè)參數(shù)属铁,后面會(huì)詳說(shuō))眠寿。

? ? ? ?問(wèn)題來(lái)了,我輕輕地焦蘑、小心地問(wèn)一下:
? ? ? ?1)你知道這3次或30次盯拱,引擎先處理哪一次?
? ? ? ?2)事實(shí)上不僅如此例嘱,那3萬(wàn)或30萬(wàn)個(gè)行狡逢,是從上而下,依次進(jìn)行嗎拼卵?
? ? ? ?3)可能奢浑,運(yùn)用已有的知識(shí),你知道能處理或定義“當(dāng)前行”的行腋腮,或“當(dāng)前行”的前多少行或后多少行......雀彼。問(wèn)題是這是你定義的(你可能需要額外引用一個(gè)序號(hào)或者編號(hào)列通過(guò)“&&”定義、或者使用變量即寡、或者專門函數(shù)定義等)徊哑,它并不是內(nèi)部引擎的執(zhí)行行為。
? ? ? 4)有太多的次數(shù)聪富、太多的行時(shí)莺丑,每次對(duì)應(yīng)處理的行數(shù)量相同嗎?等等

? ? ? ?換句話說(shuō)墩蔓,你無(wú)法控制引擎的所謂行的行為(你卻總想去搞懂它)梢莽,它始終是列表行為。你要它理解你钢拧,只有通過(guò)列表這個(gè)唯一的方式告訴它蟹漓,而不能一廂情愿炕横。否則源内,結(jié)論是,你的公式將會(huì)錯(cuò)誤(因?yàn)槟悴](méi)有了解它,如何讓它正確地工作膜钓?)嗽交。
? ? ? ?這里,我們至少已經(jīng)知道了:引擎每一次處理的不一定是一行颂斜!不是一行夫壁,當(dāng)然不能說(shuō)"一行一行“地遍歷。而且沃疮,引擎還是在以"列表的方式“執(zhí)行它(只是我們習(xí)慣了認(rèn)為它是行)盒让,從這點(diǎn)上說(shuō):行上下文="當(dāng)前行“,這里的行可不一定是我們認(rèn)為的一行司蔬,而可以是許多的行邑茄。

? ? 第9式:CALCULATE的值列表與列表

? ? ? ?可以肯定的是,行上下文是一種以行的方式運(yùn)行的行為俊啼。但顯然稱之為“行”或"當(dāng)前行“己不合適(90%的情形如此肺缕,不恰當(dāng))。更恰當(dāng)?shù)膽?yīng)該叫"值列表"授帕。
? ? ? ? 值列表并不僅僅指代數(shù)值型列表同木,而是由列基數(shù)(唯一值)所定義。比如跛十,通常我們篩選中使用的:某列="張三"彤路,指代的是列基數(shù)為"張三“的所有行的值列表。
? ? ? ? 那么偶器,通常所說(shuō)的列表是包含了該列全部基數(shù)(唯一值)的整列斩萌,而只包括某些(部分)基數(shù)的列表我們稱之為"值列表"。
? ? ? ? 你可能會(huì)想到屏轰,求列表里的行(列值)的基數(shù)與計(jì)數(shù)是稍微不同的: 只有求一列中唯一值的計(jì)算才是基數(shù)計(jì)算颊郎,此類函數(shù)有DISTINCTCOUNT(非重復(fù)計(jì)數(shù))、VALUES霎苗、? DISTINCT姆吭、COUNTROWS(FILTERS())等。它們之間在用法上有細(xì)微的差異唁盏。略内狸。

? ? ? ?不管你是針對(duì)表或表里的某個(gè)列計(jì)數(shù),你可以發(fā)現(xiàn)厘擂,基數(shù)值結(jié)果只與該列擁有的唯一值的數(shù)量有關(guān)昆淡。如圖,在透視表里(以及數(shù)據(jù)模型里)顯示出針對(duì)同一個(gè)表的整表或不同列表計(jì)算刽严。你可以理解為:你篩選某列昂灵,其實(shí)篩選的是基數(shù),你習(xí)慣了迭代的說(shuō)法,那就先理解為眨补,迭代了多少個(gè)基數(shù)管削,就執(zhí)行了多少次。

? ? ? ?也就是說(shuō)撑螺,列表始終是列表含思,不過(guò)為了方便,將它以兩種方式存在而矣(就像水的三種狀態(tài)不同甘晤,都由H2O構(gòu)成)含潘。
? ? ? ? 你應(yīng)該能發(fā)現(xiàn)并明白,由于列表的基數(shù)不同线婚,作為篩選時(shí)的篩選范圍也會(huì)不同调鬓。通常,擁有最大基數(shù)的那個(gè)列表酌伊,依需要腾窝,是可以作為關(guān)系外鍵與其他表建立關(guān)系(因?yàn)樵摿斜頁(yè)碛械幕鶖?shù)與整個(gè)模型表的基數(shù)相同)。

? ? (2)我們還可以使用SSAS的線程段的執(zhí)行來(lái)理解數(shù)據(jù)內(nèi)部的運(yùn)行居砖。SSAS總是使用某個(gè)線程段來(lái)掃描包含800萬(wàn)行或更少行的計(jì)算表虹脯,在PowerPivot中也有100萬(wàn)行!對(duì)奏候,你沒(méi)有看錯(cuò)循集,一次性運(yùn)行100萬(wàn),100萬(wàn)會(huì)是一行一行嗎蔗草?當(dāng)然這其中可以說(shuō)咒彤,它包含了多少次掃描運(yùn)行。
? ? ? 結(jié)果可能只有一行(一行的列表)或多行咒精。
? ? ? 這樣想想镶柱,有時(shí)候你不能把處理幾十萬(wàn)數(shù)據(jù)就卡頓的責(zé)任全扔給DAX引擎;
? ? ? 再如:2350000與2350001這兩個(gè)看起來(lái)很大的數(shù)放在數(shù)據(jù)模型列表里模叙,其實(shí)跟0與1沒(méi)什么區(qū)別歇拆,因?yàn)閂ertiPaq內(nèi)部可能會(huì)很聰明的使用值壓縮算法將這兩個(gè)數(shù)處理為:2350000-2350000=0、2350001-2350000=1的整數(shù)值0范咨、1來(lái)代替(引擎找到該列中的最小值故觅,然后其他列值跟它求差值比較),這是簡(jiǎn)單的理解渠啊,別糾結(jié)對(duì)錯(cuò)输吏,總之有這種情況。
? ? ? 再比如替蛉,你的數(shù)據(jù)在某個(gè)千百萬(wàn)計(jì)的行之后贯溅,突然出現(xiàn)了一個(gè)離群點(diǎn):一個(gè)超級(jí)大的數(shù)據(jù)炼杖、或超級(jí)小的數(shù)據(jù)、或某些異常數(shù)據(jù)(一個(gè)逗號(hào)盗迟?),引擎就會(huì)回過(guò)頭去重新編碼該列熙含,雖然能計(jì)算出結(jié)果罚缕,也可能造成需要很長(zhǎng)時(shí)間來(lái)運(yùn)行!

? ? ? ? 所以怎静,引擎處理的最大消耗往往來(lái)自人為的錯(cuò)誤(比如改變整列構(gòu)造的行為邮弹,或者定義了DAX無(wú)法理解的非列表行為)。
? ? ? ? 引用該定義蚓聘,我們也可以說(shuō):學(xué)習(xí)DAX的最大障礙腌乡,可能會(huì)來(lái)自你對(duì)于列表行為的理解(比如總習(xí)慣于數(shù)據(jù)庫(kù)、編程語(yǔ)言來(lái)與之溝通)夜牡。這也是我們說(shuō)干了口水也要死磕它的原因与纽。
? ? (3)我們將數(shù)據(jù)模型的不存在的東西羅列一下:VertiPaq中沒(méi)有多維數(shù)據(jù)集、也沒(méi)有度量組塘装、更沒(méi)有行或維度的概念急迂。它總以壓縮數(shù)據(jù)來(lái)有利于快速分析計(jì)算為目的!(這也是今后優(yōu)化數(shù)據(jù)或公式的依據(jù))蹦肴。
? ? ? ?方法總是會(huì)有的僚碎,為了能使用列表的語(yǔ)言形式與VertiPaq溝通,或者有一種讓它能聽(tīng)懂阴幌、能理解的方式勺阐,這就是前面我們前面提到的“值列表”。
? ? ? ?它形式上是列表(能被引擎識(shí)別并理解)矛双,同時(shí)它也是某個(gè)列里的一個(gè)或多個(gè)列值的組合(具有列值的屬性:例如可以使用加減運(yùn)算符計(jì)算渊抽、布爾值條件、以及作為邏輯條件構(gòu)建的參數(shù)等)议忽。

? ? ? 通過(guò)前面的超級(jí)啰嗦腰吟,再說(shuō)兩個(gè)由此產(chǎn)生的實(shí)用而重要的方面:

? ? ? 1)篩選器:它是某個(gè)列上的一組活動(dòng)列值(整個(gè)列值的列表或部分列值的值列表),并只適用于單個(gè)列徙瓶。請(qǐng)記住毛雇,這并不是列表篩選的正確定義。不過(guò)侦镇,在學(xué)習(xí)完許多其他方面的DAX知識(shí)前灵疮。這個(gè)定義對(duì)于開(kāi)始使用列表篩選已經(jīng)非常有用了。

? ? ? ? 注意:完成了這個(gè)話題之后壳繁,接下來(lái)的部分震捣,還將就如何更好地理解列表篩選是什么荔棉,并可以繼續(xù)更好的運(yùn)用它進(jìn)行計(jì)算進(jìn)行討論。這里先略過(guò)蒿赢。

? ? ? 我覺(jué)得我們已經(jīng)在死磕“列表”了(當(dāng)然润樱,這會(huì)很值得)。最后羡棵,我們將前面的討論歸結(jié)成一個(gè)通用的結(jié)論壹若,以方便今后在DAX的使用中運(yùn)用它解決實(shí)際問(wèn)題。這才是我們的目的皂冰。
? ? ? ?因?yàn)榈暾梗瑢?duì)于整個(gè)DAX的了解有兩個(gè)重要的關(guān)于列表的概念:篩選與計(jì)算。根據(jù)DAX語(yǔ)錄:所有DAX都是關(guān)于列表的秃流。自然赂蕴,我們分別在篩選與計(jì)算前加上列表的兩個(gè)形態(tài):值列表或列表作為限定,那就是說(shuō)DAX包括兩大部分:
? ? ?(1)值列表或列表的篩選舶胀;// 對(duì)數(shù)據(jù)列表的篩選概说,即行篩選與列表篩選。
? ? ?(2)值列表或列表的計(jì)算嚣伐。// CALCULATE( )

? ? ? ?所有DAX公式席怪,都是基于列表的兩種形態(tài):列表類型(針對(duì)列表)或列值格式(針對(duì)列值、值列表)纤控。你可以對(duì)某一個(gè)列表挂捻,分別設(shè)置列表的數(shù)據(jù)類型以及列值格式(你應(yīng)該明白了,值列表是物理列表(元列表)的衍生或派生的列表船万。它的基數(shù)總是要比元列表少(這在實(shí)際的DAX運(yùn)用中要注意刻撒,否則篩選將不起作用)。
? ? ? ?其實(shí)耿导,DAX對(duì)列類型并不敏感声怔、也能良好處理列表類型,當(dāng)你需要處理諸如在公式里使用某個(gè)特別的符號(hào)舱呻、時(shí)期轉(zhuǎn)數(shù)值等醋火,只要列表類型設(shè)置并確認(rèn)一次就行。而且必須事先這樣做箱吕,否則即便引擎能處理出結(jié)果芥驳,也會(huì)消耗內(nèi)存、減低性能茬高!

? ? ? ?最后兆旬,如果你對(duì)于DAX列表已有一定的了解。那么怎栽,接下來(lái)還會(huì)就這個(gè)話題展開(kāi)丽猬,希望它變得更易于理解和盡快投于運(yùn)用宿饱。

? ? ? 未完待續(xù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市脚祟,隨后出現(xiàn)的幾起案子谬以,更是在濱河造成了極大的恐慌,老刑警劉巖由桌,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件为黎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡沥寥,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門柠座,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)邑雅,“玉大人,你說(shuō)我怎么就攤上這事妈经』匆埃” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵吹泡,是天一觀的道長(zhǎng)骤星。 經(jīng)常有香客問(wèn)我,道長(zhǎng)爆哑,這世上最難降的妖魔是什么洞难? 我笑而不...
    開(kāi)封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮揭朝,結(jié)果婚禮上队贱,老公的妹妹穿的比我還像新娘。我一直安慰自己潭袱,他們只是感情好柱嫌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著屯换,像睡著了一般编丘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上彤悔,一...
    開(kāi)封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天嘉抓,我揣著相機(jī)與錄音,去河邊找鬼晕窑。 笑死掌眠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的幕屹。 我是一名探鬼主播蓝丙,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼级遭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了渺尘?” 一聲冷哼從身側(cè)響起挫鸽,我...
    開(kāi)封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸥跟,沒(méi)想到半個(gè)月后丢郊,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡医咨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年枫匾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拟淮。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尼啡,死狀恐怖唠梨,靈堂內(nèi)的尸體忽然破棺而出镜雨,到底是詐尸還是另有隱情苦蒿,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布委造,位于F島的核電站戳鹅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏昏兆。R本人自食惡果不足惜枫虏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爬虱。 院中可真熱鬧模软,春花似錦、人聲如沸饮潦。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)继蜡。三九已至回俐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間稀并,已是汗流浹背仅颇。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留碘举,地道東北人忘瓦。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像引颈,于是被迫代替她去往敵國(guó)和親耕皮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子境蜕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容