Power BI之DAX神功:第4卷第7回 通過橋接表實現(xiàn)多對多關(guān)系
一、前言
《權(quán)威指南》在這節(jié)課用的案例我是外行看不懂。引用書中一句話:“銀行一個賬戶可以屬于多個客戶,一個客戶可以擁有多個賬戶”。我接觸銀行是以一個儲戶的身份接觸的,對我而言,我可以在銀行開多個賬戶,但是一個賬戶不可能有多個人。比如你叫張三,你在銀行存款10萬,你這個賬戶名下還有我,我把你這10萬取走了。這叫什么事呀?但是我相信書中的案例一定有他的道理,因為我是外行我不懂。(所以說數(shù)據(jù)分析不懂自己的業(yè)務(wù)=零)
但是我可以舉一反三:下面是六套房子的產(chǎn)權(quán)人名單,房產(chǎn)證可以寫多人

如上圖所示,以孫興華為例,房產(chǎn)證ID-1,是孫興華自己買的,ID-5是孫興華和沙織一同購買,ID-6是孫興華和帕拉斯一同購買。那么這六套房中產(chǎn)權(quán)人有幾個?答案是4個

二、多對多關(guān)系有兩種情況
網(wǎng)友質(zhì)疑《權(quán)威指南》本節(jié)案例中的Accounts和Customers怎么可能是多對多關(guān)系呢?
因為多對多關(guān)系有兩種不同情況
第1種情況:就是我們最常見的,兩張表學(xué)號、課程編號都有重復(fù)

我們的處理方法:按業(yè)務(wù)將其中一張表拆分成兩個一端表,建立一對多關(guān)系

當(dāng)然也可以建立多對多關(guān)系,我們將在《DAX神功》第4卷第9回進(jìn)行講解但是不推薦使用。
第2種情況:通過一對多關(guān)系和多對一關(guān)系共同創(chuàng)建的模型,也叫多對多關(guān)系。
而書中講的橋接表案例就是在處理這第2種情況。還記得我告訴大家,能用1張表不用2張表,能用2張表不用3張表,從4張表開始不是高手就是笑話,如果你信我,這個問題就避坑了。什么是橋接表,當(dāng)兩個一端表無法建立關(guān)系時,通過一張多端表將兩張一端表連接起來。但是這張多端表可是有講究的。
橋接表(Bridge Table,簡稱BT,聽這簡稱就懂了)是比較特殊的表。
在數(shù)據(jù)庫的建模時,會遇到具有層次結(jié)構(gòu)的維度表,對于這樣的表有一種建模方式是建立父子表,即每條記錄上包括一個指向其父記錄的字段。這種父子表的建立在層級深度可變時尤其有用,是一個緊湊而有效的建模方式。所以學(xué)習(xí)橋接表前必需先知道父子層級結(jié)構(gòu)。詳見《DAX神功》第3卷第2回
三、利用M函數(shù)制作橋接表
下圖層級關(guān)系這張表就是橋接表,因為房產(chǎn)證和花名冊你無法直接建立關(guān)系。
我們需要使用M函數(shù)制作它,這個案例簡單你用DAX實現(xiàn)也可以,但是當(dāng)情況變得復(fù)雜以后,數(shù)據(jù)清洗還是M函數(shù)更專業(yè)。

Ps:發(fā)票表中的退款是什么意思?你買套期房就明白了,交房時會有測繪,當(dāng)房子建筑面積低于合同面積時,會有退款。(不過一般都補(bǔ)款,建筑面積你個人沒法算,只有專業(yè)機(jī)構(gòu)才能測。一旦建筑面積寫在房產(chǎn)證上,這個面積就是合法的,你賣房時也會按照這個面積執(zhí)行)
【1】將房產(chǎn)證這張表導(dǎo)入PowerQuery,增加一個步驟,命名:修改列

【2】對產(chǎn)權(quán)人列進(jìn)行擴(kuò)展

返回結(jié)果:

【3】將花名冊導(dǎo)入PowerQuery,兩張表做合并查詢(通過產(chǎn)權(quán)人和姓名建立關(guān)系)


我們展開花名刪那一列,只保留房主ID

返回結(jié)果:

最后:刪除產(chǎn)權(quán)人列即可。
四、體驗多對多關(guān)系第2種情況
凡是一端可以直接篩選多端的關(guān)系都是一對多關(guān)系:例如下圖所示我們可以用姓名篩選成績,用課程名稱篩選成績,因為兩個一端表都可以篩選多端表。

但是,當(dāng)我們將今天的案例導(dǎo)入后:(下圖點擊后放大)

現(xiàn)在,如果我想使用花名冊中的姓名去篩選發(fā)票表中的金額,可是箭頭不通呀
方法1:在模型中將層級關(guān)系和房產(chǎn)證這兩張表改成雙向,缺點改變了整個模型關(guān)系。
方法2:通過CROSSFILTER建立只有這一個度量值生效的雙向關(guān)系。
詳見《DAX神功》第1卷第22回

返回結(jié)果:

雙向篩選:如果直接在模型上改雙向箭頭會影響其它度量值,即便使用CROSSFILTER雖然可以無視其它度量值,但是可能會使數(shù)據(jù)模型產(chǎn)生歧義。我會在《DAX神功》第4卷第12回進(jìn)行講解
五、回憶我們講雙向箭頭時的案例
下圖是《DAX神功》第1卷第2回使用過的案例:

我們將表2和表3改成雙向箭頭(使用CROSSFILTER結(jié)果是一樣的)

建立度量值:
你看看結(jié)果是不是錯的:

原理:沒有使用橋接表,也并不是所有情況都能用橋接表完成。因為《DAX神功》第1卷第2回我要證明雙向箭頭有問題不建議你使用故意寫的幾個表。所以我經(jīng)常告訴大家,雙向箭不要用,多對多關(guān)系很復(fù)雜!表格盡量少!否則原理學(xué)到飽!
六、數(shù)據(jù)沿襲/擴(kuò)展表可以解決問題
保留數(shù)據(jù)沿襲的函數(shù)我們講了很多,第一個想到的就是TREATAS它能修改沿襲,還有一個我們在《DAX神功》第2卷第21回最后那個圖片中展示給大家了。SUMMARIZE從銷售表里獲取會員卡號去重后的表,再通過ADDColumns添加列適配度量值,如果沒有保留數(shù)據(jù)沿襲,你能給它適配度量值嗎?《DAX神功》第3卷第5回、第4卷第4回也多次使用了這個方法,同時在《DAX神功》第3卷第12回 我們學(xué)習(xí)了擴(kuò)展表原理
其實我講上面這段話的意思就是告訴大家:因為知識太多,很可能你學(xué)完就忘記了。但是我使用的知識都是講過的,而不是憑空給你堆出來的名詞。
回到我們房產(chǎn)證的案例中:

【1】擴(kuò)展表方法處理問題
層級關(guān)系這張表,它的擴(kuò)展表是:層級關(guān)系+房產(chǎn)證+花名冊 這三張表所有列,我們使用擴(kuò)展表篩選最簡單的方法。
// 同時解決了行和列的篩選

【2】利用數(shù)據(jù)沿襲特性
要分開處理行和列的問題
以上兩個度量值都能實現(xiàn)與擴(kuò)展表一樣效果,雖然相對復(fù)雜了。但是當(dāng)兩張表不在一個存儲模式中,也就是處于弱關(guān)系時,擴(kuò)展表只是它本身,那時你用不了擴(kuò)展表原理。詳見《DAX神功》第4卷第6回。如果是弱關(guān)系可以考慮使用CROSSFILTER
七、再談不符合實時參照完整性的情況

假設(shè)我們給發(fā)票發(fā)增加一行:房產(chǎn)證表中沒有520這個ID

如果這個時候使用雙向關(guān)系(無論是改箭頭,還是CROSSFILTER),當(dāng)你使用產(chǎn)權(quán)人篩選時,都會顯示空行,因為產(chǎn)權(quán)人ID=520他不知道對應(yīng)的值是什么,在房產(chǎn)證這張表里沒有號碼。如果使用數(shù)據(jù)沿襲或擴(kuò)展表就避開了這個問題。

當(dāng)然你用姓名篩選時因為新增的520是房產(chǎn)證ID,不顯示空行,但是總計仍然是697

注:總金額是修改成雙向關(guān)系后直接使用【總金額】度量值,換成CROSSFILTER方法也可以。
但是這里就出現(xiàn)一個業(yè)務(wù)問題,你的分析中是否要避開空行?如果不想避開未匹配值的數(shù)據(jù)而影響最后結(jié)果,那就使用CROSSFILTER臨時啟用雙向箭頭。否則可以使用后三種情況。由于后三個度量值:你寫成了calculate(計算器,篩選器)? ,它的篩選器被強(qiáng)制激活了,所以忽略未匹配的值。
當(dāng)你在模型中修改成雙向箭頭,使用度量值 總金額=sum('發(fā)票表'[金額])
或者使用CROSSFILTER函數(shù)改變關(guān)系時:(CROSSFILTER是調(diào)節(jié)器不是篩選器)都是由行標(biāo)題來篩選的,所以不忽略未匹配的值。

《孫興華講PowerBI火力全開》PowerBI必學(xué)課程
https://www.bilibili.com/video/BV1qa4y1H7wp
《DAX神功》文字版合集:
https://www.bilibili.com/read/readlist/rl442274
《DAX神功》視頻版合集:
https://www.bilibili.com/video/BV1YE411E7p3
《DAX神功番外篇》文字版合集:
https://www.bilibili.com/read/readlist/rl478271
PowerBI(DAX函數(shù))、PowerQuery(M函數(shù))、Python辦公自動化、Python爬蟲、Python數(shù)據(jù)分析、ExcelVBA、WordVBA、AccessVBA、MySQL等等
https://www.bilibili.com/read/cv10222110