Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Earn a 50% discount on the DP-600 certification exam by completing the Fabric 30 Days to Learn It challenge.

Reply
juncr
Regular Visitor

Flatten Parent-Child Hierarchy table with jumping levels, without M and not DAX

Hi Power BI Community,

 

I am trying to flatten a Parent-Child Hiearchy table (with jumping levels) in Power Query and I would appreciate any tips.

The context: the parent-child hierarchy table is coming from a computerized maintenance management system. 

The tricky part for me: jumping hierarchy levels. And tranforming the table in M instead of DAX.

 

This is a simplified version of the hierarchy with jumping levels. 

Skärmbild 2022-10-03 111250.png

What I want to achieve is:

AS_IS: Parent-Child Hiearchy table (The original table has ~ 300 K rows.)

Child keyParent keyHierarchy level
Comp_ASubunit_A6-COMPONENT
Subunit_AUnit_A5-SUBUNIT
Unit_AEquipment_A4-UNIT
Equipment_AProdArea_A3-EQUIPMENT
ProdArea_APlant_A2-PRODAREA
Plant_A 1-PLANT
Comp_BUnit_B6-COMPONENT
Unit_BEquipment_B4-UNIT
Equipment_BProdArea_B3-EQUIPMENT
ProdArea_BPlant_A2-PRODAREA

 

TO-BE: Flattned Hierarchy table with conditionals

Child key1-PLANT2-PRODAREA3-EQUIPMENT4-UNIT5-SUBUNIT6-COMPONENTConditional explanation
Comp_APlant_AProdArea_AEquipment_AUnit_ASubunit_AComp_A 
Subunit_APlant_AProdArea_AEquipment_AUnit_ASubunit_A  
Unit_APlant_AProdArea_AEquipment_AUnit_A   
Equipment_APlant_AProdArea_AEquipment_A    
ProdArea_APlant_AProdArea_A     
Plant_APlant_A      
Comp_BPlant_AProdArea_BEquipment_BUnit_BUnit_BComp_BIf there is a "jump" in levels, return the next parent key
Unit_BPlant_AProdArea_BEquipment_BUnit_B   
Equipment_BPlant_AProdArea_BEquipment_B    
ProdArea_BPlant_AProdArea_B     

 

I was able to flatten this table with DAX, using PATH, PAHTITEM, LOOKUPVALUE and SWITCH for each hiearchy level column. However, the target is to create the flattned table in dataflows and use it in different reports in Power BI. Therefore I need to achieve the same result with M syntax in Power Query.

 

There are no cases of multiple parents.

 

Since the case is fairly complicated, I would appreciate tips to reproduce the functions in M for PATH and PATHITEM. From there I can try to parse by a PATH column by delimiter and add the conditionals by column, I believe.

1 ACCEPTED SOLUTION
v-yalanwu-msft
Community Support
Community Support

Hi, @juncr ;

You could try it.

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45Wcs7PLYh3VNJRCi5NKs3LLAGzzXSd/X0D/P1c/UKUYnWiUeRCYQxT3eBQp1A/T4gSuLBrYWlmQW5qHoRnogtXgSoRUJSf4liUmgjmGOu6BoZ6BvjC7EORDMhJhOox0g0I8ndxDHJ1hKiCSwCRoW6AjyNUO9hPTjC3OmHxEFwC4SgnXK51QnatEz7XOuF0bSwA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Child key" = _t, #"Parent key" = _t, #"Hierarchy level" = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Child key", type text}, {"Parent key", type text}, {"Hierarchy level", type text}}),
    myfunction = (ChildCol,ParentCol,CurrentParent)=>
                    let
                    mylist=Table.Column(Table.SelectRows(#"Changed Type",each Record.Field(_,ChildCol)=CurrentParent),ParentCol),
                    result=Text.Combine(mylist)
                    in
                   
                    Text.TrimEnd(
                    if result ="" then ""  else @ result & "|" & @ myfunction(ChildCol,ParentCol,result),
                   "|"),
    Path = Table.AddColumn(#"Changed Type", 
                            "Path", each 
                                    Text.Trim(
                                        Text.Combine( List.Distinct(
                                                        List.Reverse(
                                                            List.RemoveItems(
                                                                Text.Split(myfunction("Child key","Parent key",[Child key]),"|"),{""}
                                                            )
                                                        )
                                                        &{[Parent key],[Child key]})
                                            ,
                                            "|"
                                        )
                                             ,"|"
                                    )
            )
in
    Path

The final show:

vyalanwumsft_0-1664870288955.png


Best Regards,
Community Support Team _ Yalan Wu
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

View solution in original post

1 REPLY 1
v-yalanwu-msft
Community Support
Community Support

Hi, @juncr ;

You could try it.

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45Wcs7PLYh3VNJRCi5NKs3LLAGzzXSd/X0D/P1c/UKUYnWiUeRCYQxT3eBQp1A/T4gSuLBrYWlmQW5qHoRnogtXgSoRUJSf4liUmgjmGOu6BoZ6BvjC7EORDMhJhOox0g0I8ndxDHJ1hKiCSwCRoW6AjyNUO9hPTjC3OmHxEFwC4SgnXK51QnatEz7XOuF0bSwA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Child key" = _t, #"Parent key" = _t, #"Hierarchy level" = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Child key", type text}, {"Parent key", type text}, {"Hierarchy level", type text}}),
    myfunction = (ChildCol,ParentCol,CurrentParent)=>
                    let
                    mylist=Table.Column(Table.SelectRows(#"Changed Type",each Record.Field(_,ChildCol)=CurrentParent),ParentCol),
                    result=Text.Combine(mylist)
                    in
                   
                    Text.TrimEnd(
                    if result ="" then ""  else @ result & "|" & @ myfunction(ChildCol,ParentCol,result),
                   "|"),
    Path = Table.AddColumn(#"Changed Type", 
                            "Path", each 
                                    Text.Trim(
                                        Text.Combine( List.Distinct(
                                                        List.Reverse(
                                                            List.RemoveItems(
                                                                Text.Split(myfunction("Child key","Parent key",[Child key]),"|"),{""}
                                                            )
                                                        )
                                                        &{[Parent key],[Child key]})
                                            ,
                                            "|"
                                        )
                                             ,"|"
                                    )
            )
in
    Path

The final show:

vyalanwumsft_0-1664870288955.png


Best Regards,
Community Support Team _ Yalan Wu
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

Helpful resources

Announcements
RTI Forums Carousel3

New forum boards available in Real-Time Intelligence.

Ask questions in Eventhouse and KQL, Eventstream, and Reflex.

MayPowerBICarousel

Power BI Monthly Update - May 2024

Check out the May 2024 Power BI update to learn about new features.

LearnSurvey

Fabric certifications survey

Certification feedback opportunity for the community.

Top Solution Authors
Top Kudoed Authors