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

Join us at FabCon Atlanta from March 16 - 20, 2026, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM. Register now.

Reply
Anonymous
Not applicable

Hierarchy Transformations - Level to Title

To the experts.. I'm having some trouble conceptualizing my Power Query transformation steps for the current challenge I have. I have a table that list a project, with an employee that's responsible for the project and then their tiered-leaders (Leader #1, Leader#2, etc). The tiering table includes names and titles.

What I need though is to transform that tiered table into a table that shows the projects with its responsible person and then their leaders by TITLE, not position number. I know there will be some form of any or all of PIVOT, UNPIVOT, TRANSPOSE, and the like, I just can't quite get my head around the steps. Attached is a snapshot of my initial table on top and my desired end result. Any help would be greatly appreciated.

PS: if it wasn't clear, I want to do these transformations strictly in M Code (Power Query).

Thank you in advance,
-Nate2020-08-25_22-27-53.png

ProjectPersonPerson IDLEADER 1 NameLEADER 1 IDLEADER 1 TitleLEADER 2 NameLEADER 2 IDLEADER 2 TitleLEADER 3 NameLEADER 3 IDLEADER 3 TitleLEADER 4 NameLEADER 4 IDLEADER 4 Title
T555555Joe1234John2345DirectorJim3456Vice PresidentJill4567PresidentJeff5678CEO
T777777Paul4321Carl5432SupervisorGabe6543ManagerJose7654DirectorTodd8765Vice President
T999999Joe7408Jack8519ManagerStacey9630DirectorLindsay10741Vice PresidentLauren11852President
T122222Bill10495Sandy11606DirectorDoug12717Vice PresidentLandon13828PresidentJoseph14939CEO
               
               
   Title Title Title Title Title Title 
ProjectPersonPerson IDSupervisorSupervisorIDManagerManagerIDDirectorDirectorIDVice PresidentVice PresidentIDPresidentPresidentIDCEOCEOID
T555555Joe1234    John2345Jim3456Jill4567Jeff5678
T777777Paul4321Carl5432Gabe6543Jose7654Todd8765    
T999999Joe7408  Jack8519Stacey9630Lindsay10741Lauren11852  
T122222Bill10495    Sandy11606Doug12717Landon13828Joseph14939
2 ACCEPTED SOLUTIONS
Anonymous
Not applicable

UPDATE: After doing some transformation to get my titles normalized, like I showed in the example, I solved this by just creating custom columns for each title looking at all of the leaders titles and placing their name in the proper column if their normalized title matched the column title I needed. Here are some advanced editor examples... pretty easy in reality.

 

 Director = Table.AddColumn(VP, "DIRECTOR", each if [#"SUP_1_TITLE-Groomed"] = "DIRECTOR" then [SUP_1_Name] else if [#"SUP_2_TITLE-Groomed#(cr)#(lf)"] = "DIRECTOR" then [SUP_2_Name] else if [#"SUP_3_TITLE-Groomed"] = "DIRECTOR" then [SUP_3_Name] else if [#"SUP_4#(cr)#(lf)_TITLE-Groomed"] = "DIRECTOR" then [SUP_4_Name] else "TBD"),
 
Manager = Table.AddColumn(Director, "MANAGER", each if [#"SUP_1_TITLE-Groomed"] = "MANAGER" then [SUP_1_Name] else if [#"SUP_2_TITLE-Groomed#(cr)#(lf)"] = "MANAGER" then [SUP_2_Name] else if [#"SUP_3_TITLE-Groomed"] = "MANAGER" then [SUP_3_Name] else if [#"SUP_4#(cr)#(lf)_TITLE-Groomed"] = "MANAGER" then [SUP_4_Name] else "TBD"),

 

View solution in original post

ziying35
Impactful Individual
Impactful Individual

@Anonymous 

try this:

let
    Source = Table.FromRecords(Json.Document(Binary.Decompress(Binary.FromText("hdRPb4IwGAbwr0J69kDLn4K3TcyyhW1kml3MDh1UZcPWFFhiln33FRaxllfXm09eH82P8q6+UabkB88bNEXLoD9ogjKuail09CD58NG5T9AUE8+foHR+k8xfHOw8sR3vx7YCGXE3qQcDI1qWTdWNJqXSvybVaZwMLeXOTLsS3REa0bHktcy5kylelwUXzelL3qmqqsy469JV1IiOXUCNP9Tw9dqMuxrdEhnRsWY2f0Y/kzNO2h+TM2Ntde7pewSPPWdMVbZnoEcBz0W75+qrrEHRO/bObdJQFwGkj0ywDVeQpay5bUl1C2A5frgD5VIWhU0Z6RqA0nq6lmrcn6uXlPpuBFxSln/aqFGAYwB1hDGILhqW84NtGoeeC5iOOQbUtBRFzQ62K3apjwHYSxd+4E1Zq7iwgTGOAgIIX8TFpDsm7u3fm2SuANePgzHvgoniYPtiHLohAHxlCySy3di+mFBMAeB/90Cq/5QUI2UvIhGgfHUV6Ldgvx0B+7EXA8D9Nnj7BQ==", BinaryEncoding.Base64),Compression.Deflate))),
    fd = Table.ColumnNames(Source),
   
    fx = (rec)=>
         let fnField = (txt)=> Record.Field(rec, List.Select(Record.FieldNames(rec), each Text.EndsWith(_, txt)){0})
         in  Record.AddField(Record.AddField([],fnField("Title"),fnField("Name")),fnField("Title")&"ID",fnField("ID")),
         
    recs = Table.TransformRows(
              Source, 
              (r)=> Record.SelectFields(r, List.FirstN(fd,3))&
                    Record.Combine(List.Transform(List.Split(List.Skip(fd,3),3), each fx(Record.SelectFields(r, _))))),
    toTbl = Table.FromRecords(recs, Record.FieldNames(Record.Combine(recs)), 2),
    ref_order = {"S", "M", "D", "V", "P", "C"},
    nfd = List.Sort(
             List.Skip(Table.ColumnNames(toTbl), 3), 
             {{each List.PositionOf(ref_order, _, 0, (x,y)=>Text.StartsWith(y,x)), 0}, {Text.Length, 0}}
          ),
    result = Table.ReorderColumns(toTbl, nfd)
in
    result

View solution in original post

7 REPLIES 7
ziying35
Impactful Individual
Impactful Individual

@Anonymous 

try this:

let
    Source = Table.FromRecords(Json.Document(Binary.Decompress(Binary.FromText("hdRPb4IwGAbwr0J69kDLn4K3TcyyhW1kml3MDh1UZcPWFFhiln33FRaxllfXm09eH82P8q6+UabkB88bNEXLoD9ogjKuail09CD58NG5T9AUE8+foHR+k8xfHOw8sR3vx7YCGXE3qQcDI1qWTdWNJqXSvybVaZwMLeXOTLsS3REa0bHktcy5kylelwUXzelL3qmqqsy469JV1IiOXUCNP9Tw9dqMuxrdEhnRsWY2f0Y/kzNO2h+TM2Ntde7pewSPPWdMVbZnoEcBz0W75+qrrEHRO/bObdJQFwGkj0ywDVeQpay5bUl1C2A5frgD5VIWhU0Z6RqA0nq6lmrcn6uXlPpuBFxSln/aqFGAYwB1hDGILhqW84NtGoeeC5iOOQbUtBRFzQ62K3apjwHYSxd+4E1Zq7iwgTGOAgIIX8TFpDsm7u3fm2SuANePgzHvgoniYPtiHLohAHxlCySy3di+mFBMAeB/90Cq/5QUI2UvIhGgfHUV6Ldgvx0B+7EXA8D9Nnj7BQ==", BinaryEncoding.Base64),Compression.Deflate))),
    fd = Table.ColumnNames(Source),
   
    fx = (rec)=>
         let fnField = (txt)=> Record.Field(rec, List.Select(Record.FieldNames(rec), each Text.EndsWith(_, txt)){0})
         in  Record.AddField(Record.AddField([],fnField("Title"),fnField("Name")),fnField("Title")&"ID",fnField("ID")),
         
    recs = Table.TransformRows(
              Source, 
              (r)=> Record.SelectFields(r, List.FirstN(fd,3))&
                    Record.Combine(List.Transform(List.Split(List.Skip(fd,3),3), each fx(Record.SelectFields(r, _))))),
    toTbl = Table.FromRecords(recs, Record.FieldNames(Record.Combine(recs)), 2),
    ref_order = {"S", "M", "D", "V", "P", "C"},
    nfd = List.Sort(
             List.Skip(Table.ColumnNames(toTbl), 3), 
             {{each List.PositionOf(ref_order, _, 0, (x,y)=>Text.StartsWith(y,x)), 0}, {Text.Length, 0}}
          ),
    result = Table.ReorderColumns(toTbl, nfd)
in
    result
Anonymous
Not applicable

I just applied this in a blank query and am astonished at how simple the transformations are. I don't know M well enought to know what you did here but it's definitely simpler than what I came up with

ziying35
Impactful Individual
Impactful Individual

@Anonymous 

In short, my code is to take the value of each person's job field from the three information fields, and use this value to rename all the information fields belonging to him, while deleting his original job field, and finally sort all the fields of the table according to the rank of the position.

My code used in some of the syntax in the official documentation which can not necessarily be found, see my code requires some time and experience, I hope you help!

Anonymous
Not applicable

UPDATE: After doing some transformation to get my titles normalized, like I showed in the example, I solved this by just creating custom columns for each title looking at all of the leaders titles and placing their name in the proper column if their normalized title matched the column title I needed. Here are some advanced editor examples... pretty easy in reality.

 

 Director = Table.AddColumn(VP, "DIRECTOR", each if [#"SUP_1_TITLE-Groomed"] = "DIRECTOR" then [SUP_1_Name] else if [#"SUP_2_TITLE-Groomed#(cr)#(lf)"] = "DIRECTOR" then [SUP_2_Name] else if [#"SUP_3_TITLE-Groomed"] = "DIRECTOR" then [SUP_3_Name] else if [#"SUP_4#(cr)#(lf)_TITLE-Groomed"] = "DIRECTOR" then [SUP_4_Name] else "TBD"),
 
Manager = Table.AddColumn(Director, "MANAGER", each if [#"SUP_1_TITLE-Groomed"] = "MANAGER" then [SUP_1_Name] else if [#"SUP_2_TITLE-Groomed#(cr)#(lf)"] = "MANAGER" then [SUP_2_Name] else if [#"SUP_3_TITLE-Groomed"] = "MANAGER" then [SUP_3_Name] else if [#"SUP_4#(cr)#(lf)_TITLE-Groomed"] = "MANAGER" then [SUP_4_Name] else "TBD"),

 

Icey
Community Support
Community Support

Hi @Anonymous ,

 

Glad to hear that the problem has been solved. Please accept your reply as the solution.

In addition, I can't reproduce your results. Could you share us more details or just a dummy .pbix file? I really want to know how you did it. Your contribution is highly appreciated.😀

 

 

 

Best regards

Icey

ziying35
Impactful Individual
Impactful Individual

Hi, @Anonymous 

Your problem shouldn't be too hard to solve, but I'm too slow to get this data into the table from the screenshot you provided. Can you upload your example table to the cloud, and then share the link here?

Anonymous
Not applicable

Thank you for your response. I added the table-concepts to the post. I think they can be copy and pasted from there

 

Helpful resources

Announcements
FabCon Global Hackathon Carousel

FabCon Global Hackathon

Join the Fabric FabCon Global Hackathon—running virtually through Nov 3. Open to all skill levels. $10,000 in prizes!

October Power BI Update Carousel

Power BI Monthly Update - October 2025

Check out the October 2025 Power BI update to learn about new features.

FabCon Atlanta 2026 carousel

FabCon Atlanta 2026

Join us at FabCon Atlanta, March 16-20, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.

Top Kudoed Authors