Thinking in DAX with PowerBI - 邏輯框架 - 數(shù)據(jù)結(jié)構(gòu)

上接?邏輯框架 - 計算邏輯,接下來的問題是數(shù)據(jù)結(jié)構(gòu)。
數(shù)據(jù)結(jié)構(gòu),顧名思義,就是數(shù)據(jù)擺放的狀態(tài)。例如:數(shù)據(jù)按表,集合,列表等形式擺放。
另外,當(dāng)數(shù)據(jù)結(jié)構(gòu)是表的時候,還包括了表之間的關(guān)系。對于這點,我們再另外研究。
在 PowerBI DAX 中,為了簡化,數(shù)據(jù)結(jié)構(gòu)只有一種表面形態(tài):表。那當(dāng)需要按照不同邏輯結(jié)構(gòu)思考問題的時候,如何從表的結(jié)構(gòu)形態(tài)衍生出其他結(jié)構(gòu)形態(tài)?
將表作為表
將表作為表,是很自然的。例如:
{1}這就表示了一個表,在 PowerBI DAX 中創(chuàng)建后,得到:

這里并沒有給定表的列名,系統(tǒng)會自動按Value給出,當(dāng)涉及多列時,例如:
{
(1,"Anna",23),
(2,"Tom",27)
}得到:

這里并沒有給定表的列名,系統(tǒng)會自動按Value加上列序號給出。
表與值的轉(zhuǎn)化
在參與運算時,若某個表中只有一行一列,則可以被作為值。
這里常用的一個 DAX 函數(shù)有:VALUES,這用來從一個表中提取一列(會自動非重復(fù)化),例如:

這里請注意兩點:
1、度量值的定義是正確的;
2、度量值的使用結(jié)果也是符合預(yù)期的。
但如果使用多值的表列,會得到這樣的結(jié)果:

這里也請注意兩點:
1、度量值的定義是正確的;
2、度量值的使用結(jié)果是不符合預(yù)期的。
這是初學(xué)者常常出現(xiàn)的問題,從邏輯來看:

當(dāng)VALUES函數(shù)直接用于度量值時,DAX 引擎僅僅檢查語法,是沒有錯誤的;但只有在用戶使用該度量值的運行時,才會真正計算,得到了含有多個值的結(jié)果(也是一個表),且提示用戶:表中應(yīng)該具有單個值。準(zhǔn)確講:只有當(dāng)表中具有單個值的時候,才能轉(zhuǎn)換成為值,進(jìn)而顯示。
說明
由于微軟在界面設(shè)計上實在是,這種錯誤的提示,居然是大叉子,而且錯誤信息也讓人心生恐懼,初學(xué)者往往認(rèn)為自己犯了大錯,或觸發(fā)了軟件的 BUG,而實際上,軟件只是正確地運行用戶的意圖。用?
VALUES?從表中取值,除非用戶腦中想的就是這個。
初學(xué)者常常問到:那該怎么辦?這個問題其實要問自己:當(dāng)?shù)玫搅艘粋€列表后,要進(jìn)一步做什么?是求和,還是顯示出來,然后再用 DAX 函數(shù)來操作,確保度量值可以顯示正確的結(jié)果。
將表作為列表
在某些場景,往往需要對一列元素進(jìn)行操作,從邏輯結(jié)構(gòu)上,這更符合將其看成是列表,例如:產(chǎn)品ID列表,客戶ID列表,訂單ID列表等,往往下一步就是對列表進(jìn)行迭代,在迭代中做一些事情。在經(jīng)典的 ABC 分析中,需要計算元素列表的積累 KPI 值,則有:
// 假設(shè):
KPI = SUM( 'Order'[Sales] )
// 那么:
KPI.積累 =
VAR _value = [KPI] // 當(dāng)前元素的 KPI
VAR _value_total = CALCULATE( [KPI], ALLSELECTED( ) ) // 全局元素的 KPI
// 構(gòu)建視圖層匯總表
VAR _v_table = CALCULATETABLE(
ADDCOLUMNS( VALUES( 'Product'[Product] ) , "@Value" , [KPI]),
ALLSELECTED( )
)
// 視圖層計算
RETURN SUMX( _v_table , ( [@Value] >= _value ) * [@Value] ) / _value_total其中:ADDCOLUMNS( VALUES( 'Product'[Product] ) , "@Value" , [KPI值])就是將產(chǎn)品作為一個列表,再為列表中的每個產(chǎn)品分別計算[KPI]。
注意
這里對于
[KPI]的計算,會在迭代'Product'[Product]的時候,發(fā)生上下文轉(zhuǎn)換。即:正在計算的當(dāng)前的產(chǎn)品所在行,會轉(zhuǎn)換為對某個產(chǎn)品的篩選作用于整個數(shù)據(jù)模型進(jìn)行對[KPI]的計算。可以直觀地想象成:在迭代每個產(chǎn)品時,在當(dāng)前產(chǎn)品,向下?lián)迫?yīng)的訂單計算。其中,“向下?lián)迫?yīng)的”這幾個字就表現(xiàn)了上下文轉(zhuǎn)換的邏輯動機,那就是:從宏觀層面的某個元素,轉(zhuǎn)換為對微觀層面的整層篩選,實現(xiàn)了宏觀迭代到微觀篩選的轉(zhuǎn)換。因此,上下文轉(zhuǎn)換的本質(zhì)其實正是:宏觀迭代到微觀篩選的轉(zhuǎn)換。在數(shù)據(jù)模型中,很多計算的確是要建立在不同層面之間的,那么這種宏觀迭代到微觀篩選的轉(zhuǎn)換便是在不同層面取數(shù)的核心邏輯。
將表作為集合
下面以留存客戶數(shù)的計算為例,來體會集合的邏輯結(jié)構(gòu):
User.流失留存.留存客戶數(shù) =
//
// --------- A : X period ------------|----- B : y period ------|
// ↑d1 d2↑
// ↑
//
// 設(shè)置 x
VAR _month_number_x = 6
// 設(shè)置 y
VAR _month_number_y = 1
// 以下請勿修改
VAR _users_period_a =
CALCULATETABLE(
VALUES( 'Order'[CustomerID] ) ,
DATESINPERIOD(
'Calendar'[Date] ,
DATEADD( LASTDATE( 'Calendar'[Date] ) , - _month_number_y , MONTH ) ,
- _month_number_x ,
MONTH
)
)
VAR _users_period_b =
CALCULATETABLE(
VALUES( 'Order'[CustomerID] ) ,
DATESINPERIOD(
'Calendar'[Date] ,
LASTDATE( 'Calendar'[Date] ) ,
- _month_number_y ,
MONTH
)
)
RETURN COUNTROWS( INTERSECT( _users_period_a , _users_period_b ) )留存用戶數(shù),在 DAX 種,通常指的是,對于指定的區(qū)間 [d1,d2],所在區(qū)間為 B,那么區(qū)間 A 的訪問用戶,在該 B 區(qū)間仍然訪問的視為留存,其人數(shù)為留存數(shù)。
這里,有一個自然的邏輯:A 區(qū)間的用戶集合,B 區(qū)間的用戶集合,而 A,B 的交集正是留存的用戶集合,其行數(shù)則為用戶數(shù)。
這樣,我們就把復(fù)雜的問題轉(zhuǎn)換求兩個集合,在這個案例中是兩個用戶 ID 的集合,因為用戶 ID 代表了用戶本身。
注意
上述內(nèi)容來自 DAX 模板工具:DAX Pro,可以通過拖拽鼠標(biāo),快速創(chuàng)建度量值。您也可以理解學(xué)習(xí)上述 DAX 中的邏輯后在自己的模型中實驗。
總結(jié)
在 DAX 中,常見的數(shù)據(jù)結(jié)構(gòu)有四種:
作為表(Table)的表,常常與其他表通過關(guān)系構(gòu)成更復(fù)雜的結(jié)構(gòu)。(后續(xù)文章,我們進(jìn)一步研究)
作為值(Value)的表,分析師必須確保在運行時可以的確只返回一個值。
作為列表(List)的表,通常會對一個列表進(jìn)行迭代,而在迭代中往往要施加上下文轉(zhuǎn)換來切換宏觀和微觀進(jìn)行取數(shù)。
作為集合(Set)的表,通常會對兩個集合做交,并,補的集合操作以便得到所需元素。
這就指導(dǎo)我們在面對一個問題時,我們要考慮表示該問題的數(shù)據(jù)結(jié)構(gòu)應(yīng)該強調(diào)的是什么,然后想辦法來構(gòu)建這些的數(shù)據(jù)結(jié)構(gòu),再基于數(shù)據(jù)結(jié)構(gòu)來進(jìn)行計算。
結(jié)合算法結(jié)構(gòu),我們不難看出:
計算方法,依賴于數(shù)據(jù)結(jié)構(gòu)
計算方法,構(gòu)建出數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu),為支撐計算方法
數(shù)據(jù)結(jié)構(gòu),由計算方法給出
他們之間有緊密的共生關(guān)系,這希望大家可以在實踐中加以體會理解。
另外,本文揭示了上下文轉(zhuǎn)換的本質(zhì):宏觀微觀切換。即從相對宏觀層面的元素迭代,再切換到微觀去篩選,俗稱:向下?lián)迫∠嚓P(guān)數(shù)據(jù)。
啟發(fā):DAX 是什么,并不是最重要的,重要的是如何設(shè)計簡單的規(guī)則來完成數(shù)據(jù)建模中的必備邏輯,且規(guī)則最少,那么這些規(guī)則的本質(zhì)應(yīng)該是什么,這是穿透看似復(fù)雜的 DAX 回歸簡單的思路,故稱:Thinking in DAX。
——
? 活動預(yù)告:
2020年10月22日 19點?直播:讓 PowerBI DAX 回歸簡單??
報名方法:進(jìn)入?讓 PowerBI DAX 回歸簡單 - 在線直播活動?【閱讀原文】。

讓數(shù)據(jù)真正成為你的力量
Create value?through?simple and?easy?with fun?by PowerBI
Excel BI?|?DAX Pro?|?DAX?權(quán)威指南?|?線下VIP學(xué)習(xí)
掃碼與PBI精英一起學(xué)習(xí),驗證碼:data2020
PowerBI MVP 帶你正確而高效地學(xué)習(xí) PowerBI
點擊“閱讀原文”,即刻開始
↙
