【案例】用PowerQuery處理父-子層級結(jié)構(gòu)

首先說明的是碌奉,這個帖子的思路來源于Ivan Bondarenko劝贸。我在遇到此問題無解時google到他的解決辦法潮罪。經(jīng)過摸索試驗,解決了我的問題领斥。

需要解決的問題

我遇到的問題如下:


上下級單位

我需要構(gòu)建出下圖中的組織機構(gòu)層級來:

組織機構(gòu)層級
let
    上下級拆分 = if List.ContainsAll(Table.ColumnNames(原始數(shù)據(jù)),{"上級單位","下級單位"})  then 
 let
    源 = Append1,
    重命名的列 = Table.RenameColumns(源,{{"上級單位", "Parent"}, {"下級單位", "Child"}}),
    刪除的其他列 = Table.SelectColumns(重命名的列,{"Parent", "Child"}),
    自定義1 = Table.InsertRows(刪除的其他列,0,{[Parent="煤礦安全生產(chǎn)標(biāo)準(zhǔn)化直通車",Child="煤礦安全生產(chǎn)標(biāo)準(zhǔn)化直通車"]}),
    buffer = Table.Buffer(自定義1),
// Child and Parent must be equal for RootElement
//    RootElement = "Company",
    RootElement = Table.SelectRows( buffer, each [Child] = [Parent] )[Child]{0},

    // Get depth of each child
    fGetDepthLevel = (child as text, optional level_counter as nullable number) =>
        let
            Level = if level_counter = null then 2 else level_counter,
            parent = buffer[Parent]{ List.PositionOf( buffer[Child], child ) },
            res = if parent = RootElement then Level else @fGetDepthLevel( parent, Level + 1 )
        in 
            res,

    buffer_w_HD = Table.Buffer( Table.AddColumn(
                                                Table.AddColumn( buffer, "HierarchyDepth", each 
                                                    if [Child] = [Parent] then 1 
                                                    else fGetDepthLevel( [Child] )
                                              ),
                                    "Level 1", each RootElement ) ),
                                    

    fGetParentByLevel = (child as text, parent_level as number) =>
        let
            // search position of Child and take its Hierarchy Depth
            parent_level_result = buffer_w_HD[HierarchyDepth]{ List.PositionOf( buffer_w_HD[Child], child ) },
            // if it is desired Depth - take this Child
            res = if parent_level_result = parent_level 
                  then child 
            // otherwise - search further
                  else @fGetParentByLevel( buffer_w_HD[Parent]{ List.PositionOf( buffer_w_HD[Child], child ) }, parent_level )                    
        in res,
    
    HierarchyDepth = List.Max( buffer_w_HD[HierarchyDepth] ),

    table_generator_buffered = Table.Buffer( 
           List.Last(
                List.Generate( ()=>
                    [i = 2, T = buffer_w_HD],
                    each [i] <= HierarchyDepth + 1,
                    each [i = [i] + 1,
                          T = Table.AddColumn( [T], "Level " & Text.From( [i] ), each if [HierarchyDepth] >=i-1 then fGetParentByLevel( [Child], i-1 ) else null )  ],
//                            T = Table.AddColumn( [T], "Level " & Text.From( [i] ), each if [HierarchyDepth] >=[i]-1 then fGetParentByLevel( [Child], [i]-1 ) else null )  ],
                    each [T] ) ) ),

    IsLeaf = Table.AddColumn( table_generator_buffered, "IsLeaf", each not List.Contains( table_generator_buffered[Parent], [Child] ) )
in
    IsLeaf

else null,
    #"Reordered Columns" = Table.ReorderColumns(上下級拆分,{"Parent", "Child", "Level 1", "Level 2", "Level 3", "Level 4", "Level 5", "HierarchyDepth", "IsLeaf"})
in
    #"Reordered Columns"

使用這段代碼嫉到,有兩個地方需要注意:
1.必須確保“上級單位”列中的每一個值都出現(xiàn)在“下級單位”列中月洛,否則代碼會出錯何恶。
2.必須設(shè)置根節(jié)點,根節(jié)點在這個例子中是以下面這段代碼來實現(xiàn)的:

自定義1 = Table.InsertRows(刪除的其他列,0,{[Parent="煤礦安全生產(chǎn)標(biāo)準(zhǔn)化直通車",Child="煤礦安全生產(chǎn)標(biāo)準(zhǔn)化直通車"]}),

可以看到對根節(jié)點來說嚼黔,parent和child是同一個值细层。如果根節(jié)點已經(jīng)存在并且在parent列和child列中的值相等,則無需這一步唬涧。

那么疫赎,如何確保上級單位(parent)的值都出現(xiàn)在下級單位( child)中呢?我采取了一個暴力辦法:將例子中的表格分別拆分為兩個查詢碎节,一個只包含“上級單位”列捧搞,一個只包含“下級單位”列,然后兩個合并狮荔,保留只出現(xiàn)在“上級單位”這個表中的值胎撇。然后這些值的上級單位都設(shè)置為根節(jié)點(也就是本例中的“礦安全生產(chǎn)標(biāo)準(zhǔn)化直通車”)。再把結(jié)果和原始表格合并殖氏,就得到了比較完備的上下級單位列表了晚树。之后再運行那段長代碼即可。

代碼中雅采,"HierarchyDepth"和"IsLeaf"與本例關(guān)系不大爵憎,我偷懶沒有刪除慨亲。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市纲堵,隨后出現(xiàn)的幾起案子巡雨,更是在濱河造成了極大的恐慌,老刑警劉巖席函,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铐望,死亡現(xiàn)場離奇詭異,居然都是意外死亡茂附,警方通過查閱死者的電腦和手機正蛙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來营曼,“玉大人乒验,你說我怎么就攤上這事〉仝澹” “怎么了锻全?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長录煤。 經(jīng)常有香客問我鳄厌,道長,這世上最難降的妖魔是什么妈踊? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任懦窘,我火速辦了婚禮肩刃,結(jié)果婚禮上递宅,老公的妹妹穿的比我還像新娘任斋。我一直安慰自己,他們只是感情好露筒,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布呐伞。 她就那樣靜靜地躺著,像睡著了一般慎式。 火紅的嫁衣襯著肌膚如雪荸哟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天瞬捕,我揣著相機與錄音鞍历,去河邊找鬼。 笑死肪虎,一個胖子當(dāng)著我的面吹牛劣砍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播扇救,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼刑枝,長吁一口氣:“原來是場噩夢啊……” “哼香嗓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起装畅,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤靠娱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后掠兄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體像云,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年蚂夕,在試婚紗的時候發(fā)現(xiàn)自己被綠了迅诬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡婿牍,死狀恐怖侈贷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情等脂,我是刑警寧澤俏蛮,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站上遥,受9級特大地震影響搏屑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜露该,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望第煮。 院中可真熱鬧解幼,春花似錦、人聲如沸包警。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽害晦。三九已至特铝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間壹瘟,已是汗流浹背鲫剿。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留稻轨,地道東北人灵莲。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像殴俱,于是被迫代替她去往敵國和親政冻。 傳聞我的和親對象是個殘疾皇子枚抵,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)明场,斷路器汽摹,智...
    卡卡羅2017閱讀 134,715評論 18 139
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J的外補...
    _Yfling閱讀 13,761評論 1 92
  • 紅黑樹是平衡二叉查找樹的一種苦锨。為了深入理解紅黑樹逼泣,我們需要從二叉查找樹開始講起。 BST 二叉查找樹(Binary...
    kanehe閱讀 1,379評論 0 8
  • 【姓名】吳從嚴 【導(dǎo)師】袁文魁 【分舵】文魁派第一分舵 【舵主】劉麗瓊 【導(dǎo)圖解說】 中心圖逆屡。袁老師分享的六大記憶...
    希波克拉底先生閱讀 329評論 0 2
  • 時不時的就耍一下圾旨,可我并不是矯情的人。 圍巾真是個好東西魏蔗。 多久沒三點前睡過覺了砍的。 作息飲食都不規(guī)律了。 寶寶們還...
    目分青見閱讀 151評論 0 0