Forum Discussion

moizsherwani's avatar
moizsherwani
Icon for Continued Contributor rankContinued Contributor
7 years ago
Solved

Parent-Child Hierarchy - Highest Parent (using Power Query not DAX)

Hello PBI Forum,

 

So my issue is as follow, I have a parent child relationship as given below and I need (within Power Query and not DAX) a way to find out the highest parent of any child

 

Team ID - Parent ID

1            - null

2            -  null

3            - 1

4            - 3 

5            - 2

6            - 5

 

Result should be as follows

 

Team ID - Highest Parent ID

1            - null

2            - null

3            - 1

4            - 1

5            - 2

6            - 2

 

So esentially need to go up the tree to the highest parent that exists. I need for this to happen at the Power Query level

 

Thanks,

 

Moiz

 

 

  • LivioLanzo's avatar
    LivioLanzo
    7 years ago

    you just need to change the data types then like this: 

     

    let
        Source = Excel.CurrentWorkbook(){[Name="Hierarchy"]}[Content],
    
        ChangedType = Table.TransformColumnTypes(Source,{{"Team ID", type text}, {"Parent ID", type text}}),
    
        ListTeamID = List.Buffer( ChangedType[Team ID] ),
        ListParentID = List.Buffer( ChangedType[Parent ID] ),
    
    
        fnGetHighestParent =  (n as text) as text =>
            let
                PosOfParent = List.PositionOf( ListTeamID, n ),
                ParID = ListParentID{PosOfParent}
             in
                if ParID = null then ListTeamID{PosOfParent} else @fnGetHighestParent(ListParentID{PosOfParent}),
    
    
        FinalTable = Table.AddColumn( ChangedType, 
                                      "HighestParent", 
                                      each  fnGetHighestParent( [Team ID] ), 
                                       type text)
        
    in
       FinalTable

14 Replies

  • Try this (your table name is Hierarchy):

     

     

    let
        Source = Excel.CurrentWorkbook(){[Name="Hierarchy"]}[Content],
    
        ChangedType = Table.TransformColumnTypes(Source,{{"Team ID", Int64.Type}, {"Parent ID", Int64.Type}}),
    
        ListTeamID = List.Buffer( ChangedType[Team ID] ),
        ListParentID = List.Buffer( ChangedType[Parent ID] ),
    
    
        fnGetHighestParent =  (n as number) as number =>
            let
                PosOfParent = List.PositionOf( ListTeamID, n ),
                ParID = ListParentID{PosOfParent}
             in
                if ParID = null then ListTeamID{PosOfParent} else @fnGetHighestParent(ListParentID{PosOfParent}),
    
    
        FinalTable = Table.AddColumn( ChangedType, 
                                      "HighestParent", 
                                      each if 
                                                [Parent ID] = null 
                                            then 
                                                null 
                                            else 
                                                 fnGetHighestParent( [Team ID] ), 
                                       type number )
        
    in
       FinalTable
  • PattemManohar's avatar
    PattemManohar
    Icon for Community Champion rankCommunity Champion

    I tried below and it worked out fine..

     

    1. Create an Alias/Duplicate table for the main table

    2. Use Merge Queries to merge both Main & Duplicate table joining ParentID in Duplicate table with TeamID in Main table (Left Outer Join).

    3. You can see a tabular new field, expand it.

    4. Add a conditional column, to have ParentID from Main table in case it is NULL in Duplicate table

     

    Here is the code for the above steps:

     

    TableName : HighParent

    DuplicateTableName : HighParentDup

     

    let
    Source = Table.NestedJoin(HighParentDup,{"ParentID"},HighParent,{"TeamID"},"HighParent",JoinKind.LeftOuter),
    #"Expanded HighParent" = Table.ExpandTableColumn(Source, "HighParent", {"TeamID", "ParentID"}, {"HighParent.TeamID", "HighParent.ParentID"}),
    #"Sorted Rows" = Table.Sort(#"Expanded HighParent",{{"TeamID", Order.Ascending}}),
    #"Added Conditional Column" = Table.AddColumn(#"Sorted Rows", "FinalParent", each if [HighParent.ParentID] = null then [ParentID] else [HighParent.ParentID]),
    #"Removed Columns" = Table.RemoveColumns(#"Added Conditional Column",{"HighParent.TeamID", "HighParent.ParentID"})
    in
    #"Removed Columns"

    • moizsherwani's avatar
      moizsherwani
      Icon for Continued Contributor rankContinued Contributor
      Thanks for your reply. The issue is that unlike the example in reality there maybe upto 6 levels of children so your solution may not be feasible. Thoughts?
      • LivioLanzo's avatar
        LivioLanzo
        Icon for Solution Sage rankSolution Sage

        moizsherwani As far as I know, my code should work on your real dataset

         

        could you post a dataset on which it does not work ?