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

Join us for an expert-led overview of the tools and concepts you'll need to become a Certified Power BI Data Analyst and pass exam PL-300. Register now.

Reply
mim
Advocate V
Advocate V

filter a path with two parents

Hello

 

I have a table with Parent_Id, Child_ID,  I want to add a third column, when for a particular Child_id, it will show if the rows belong to the path or not.

 

the dax function Path works well, but only if 1 child has 1 parent, which is not my case.

 

cheers

Mi1.JPGCapture.JPG

1 ACCEPTED SOLUTION
ImkeF
Community Champion
Community Champion

Hi mim,

this is a variation of my pattern to dynamically flatten parent-child-hierarchies. I've twitched it a bit to cover multiple parents as well. Cannot see any flaws at the moment, but you'd do me a favour to test it thoroughly. Would like to write a post for this forum here, if it works successfully, as I think that this would be useful for others as well 🙂

 

(TableName, ParentColumnName as text, ChildColumnName as text) =>

let

// Prepare input data
    ParChTable = TableName,
    #"Renamed Columns1" = Table.RenameColumns(ParChTable,{{ChildColumnName, "NodeKey"}, {ParentColumnName, "ParentKey"}}),
    Custom1 = List.Difference(List.Distinct(#"Renamed Columns1"[ParentKey]), List.Distinct(#"Renamed Columns1"[NodeKey])),
    #"Converted to Table" = Table.FromList(Custom1, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "NodeKey"}}),
    #"Appended Query" = Table.Combine({#"Renamed Columns", #"Renamed Columns1"}),
    Name = Table.AddColumn(#"Appended Query", "Name", each "Item" & Text.From([NodeKey])),
    InputTable = Table.AddIndexColumn(Name, "Index", 0, 1),
    ChildKey = "NodeKey",
    ParentKey = "ParentKey",
    LevelColumnName = "Name",

// Retrieve all parents per row
    fnAllParents = Table.AddColumn(InputTable, "AllParents", each List.Generate(()=>
    [Parent=Record.Field(_, ParentKey)],
    each [Parent] <> null and [Parent] <> "",
    each [ Parent = Table.Column(Table.SelectRows(InputTable, (ParChTable) => Record.Field(ParChTable, ChildKey) = [Parent] ), ParentKey){0} ],
    each [Parent])),
// Calculate Max Browse Depth as parameter
    MaxBrowseDepth = List.Max(List.Transform(fnAllParents[AllParents], each List.Count(_)))+1,
// Collect and sort all items for PathItems
    PathItems = Table.AddColumn(fnAllParents, "PathItems", each List.Union({List.Sort([AllParents]), {Record.Field(_, ChildKey)}})),
// Hierarchy Depth of current row
    HierarchyDepth = Table.AddColumn(PathItems, "HierarchyDepth", each List.Count([AllParents])+1),
// Check if is leaf
    Leaf = Table.AddColumn(HierarchyDepth, "IsLeaf", each if [HierarchyDepth]=MaxBrowseDepth then true else false),
// Create String Hiearchy Path (PathItems equivalent)
    HierarchyPath = Table.AddColumn(Leaf, "HierarchyPath", each Text.Combine(List.Transform([PathItems], each Text.From(_)), "|")),
// Create table for pivoting levels
    PivotTable = Table.AddColumn(HierarchyPath, "PivotTable", each Table.AddIndexColumn(Table.FromColumns({List.Union({[PathItems], List.Repeat({List.Last([PathItems])}, MaxBrowseDepth-[HierarchyDepth]+1)})}), "Level",1,1)),
// Expand pivot-level table
    #"Expanded PivotTable" = Table.ExpandTableColumn(PivotTable, "PivotTable", {"Column1", "Level"}, {"Column1", "Level"}),
// Lookup values from the name column for the level-pivots
    MergeForAccountName = Table.NestedJoin(#"Expanded PivotTable",{"Column1"},InputTable,{ChildKey},"NewColumn",JoinKind.LeftOuter),
// Expand name column
    ExpandAccountname = Table.ExpandTableColumn(MergeForAccountName, "NewColumn", {LevelColumnName}, {"LevelColumnName"}),
// Cleanup
    #"Removed Columns" = Table.RemoveColumns(ExpandAccountname,{"Column1", "AllParents", "PathItems"}),
// Create helper column for pivot column names
    AddLevel = Table.AddColumn(#"Removed Columns", "Merge", each "Level "),
    // Merge for pivot column names
    MergeLevel = Table.CombineColumns(Table.TransformColumnTypes(AddLevel, {{"Level", type text}}, "de-DE"),{"Merge", "Level"},Combiner.CombineTextByDelimiter("", QuoteStyle.None),"Level" as text),
// New step: Remove dups
    #"Removed Duplicates" = Table.Distinct(MergeLevel, {"NodeKey", "ParentKey", "HierarchyPath", "Level"}),
// Create dynamic number of level-columns by pivoting
    #"Pivoted Column1" = Table.Pivot(#"Removed Duplicates", List.Distinct(#"Removed Duplicates"[Level]), "Level", "LevelColumnName")
in
    #"Pivoted Column1"

 

Link to file: https://www.dropbox.com/s/pqaxcy4e35t6oe5/DynamicPCHierarchy.pbix?dl=0 

Imke Feldmann (The BIccountant)

If you liked my solution, please give it a thumbs up. And if I did answer your question, please mark this post as a solution. Thanks!

How to integrate M-code into your solution -- How to get your questions answered quickly -- How to provide sample data -- Check out more PBI- learning resources here -- Performance Tipps for M-queries

View solution in original post

12 REPLIES 12
ImkeF
Community Champion
Community Champion

Hi @akhilduvvuru ,
this could happen if you have a circular dependency in your data. Adding a counter to the iteration with a max of 20 would stop the iteration after this round and hopefully return the problematic rows at the bottom of the table:

(TableName, ParentColumnName as text, ChildColumnName as text) =>

let

// Prepare input data
    ParChTable = TableName,
    #"Renamed Columns1" = Table.RenameColumns(ParChTable,{{ChildColumnName, "NodeKey"}, {ParentColumnName, "ParentKey"}}),
    Custom1 = List.Difference(List.Distinct(#"Renamed Columns1"[ParentKey]), List.Distinct(#"Renamed Columns1"[NodeKey])),
    #"Converted to Table" = Table.FromList(Custom1, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "NodeKey"}}, MissingField.Ignore),
    #"Appended Query" = Table.Combine({#"Renamed Columns", #"Renamed Columns1"}),
    Name = Table.AddColumn(#"Appended Query", "Name", each "Item" & Text.From([NodeKey])),
    InputTable = Table.Buffer(Table.AddIndexColumn(Name, "Index", 0, 1)),
    ChildKey = "NodeKey",
    ParentKey = "ParentKey",
    LevelColumnName = "Name",

// Retrieve all parents per row
    fnAllParents = Table.AddColumn(InputTable, "AllParents", each List.Generate(()=>
    [Parent=Record.Field(_, ParentKey), Counter = 0],
    each [Parent] <> null and [Parent] <> "" and [Counter] < 20,,
    each [ Parent = Table.Column(Table.SelectRows(InputTable, (ParChTable) => Record.Field(ParChTable, ChildKey) = [Parent] ), ParentKey){0},
Counter = [Counter] + 1 ],
    each [Parent])),
// Calculate Max Browse Depth as parameter
    MaxBrowseDepth = List.Max(List.Transform(fnAllParents[AllParents], each List.Count(_)))+1,
// Collect and sort all items for PathItems
    PathItems = Table.AddColumn(fnAllParents, "PathItems", each List.Union({List.Sort([AllParents]), {Record.Field(_, ChildKey)}})),
// Hierarchy Depth of current row
    HierarchyDepth = Table.AddColumn(PathItems, "HierarchyDepth", each List.Count([AllParents])+1),
// Check if is leaf
    Leaf = Table.AddColumn(HierarchyDepth, "IsLeaf", each if [HierarchyDepth]=MaxBrowseDepth then true else false),
// Create String Hiearchy Path (PathItems equivalent)
    HierarchyPath = Table.AddColumn(Leaf, "HierarchyPath", each Text.Combine(List.Transform([PathItems], each Text.From(_)), "|")),
// Create table for pivoting levels
    PivotTable = Table.AddColumn(HierarchyPath, "PivotTable", each Table.AddIndexColumn(Table.FromColumns({List.Union({[PathItems], List.Repeat({List.Last([PathItems])}, MaxBrowseDepth-[HierarchyDepth]+1)})}), "Level",1,1)),
// Expand pivot-level table
    #"Expanded PivotTable" = Table.ExpandTableColumn(PivotTable, "PivotTable", {"Column1", "Level"}, {"Column1", "Level"}),
// Lookup values from the name column for the level-pivots
    MergeForAccountName = Table.NestedJoin(#"Expanded PivotTable",{"Column1"},InputTable,{ChildKey},"NewColumn",JoinKind.LeftOuter),
// Expand name column
    ExpandAccountname = Table.ExpandTableColumn(MergeForAccountName, "NewColumn", {LevelColumnName}, {"LevelColumnName"}),
// Cleanup
    #"Removed Columns" = Table.RemoveColumns(ExpandAccountname,{"Column1", "AllParents", "PathItems"}),
// Create helper column for pivot column names
    AddLevel = Table.AddColumn(#"Removed Columns", "Merge", each "Level "),
    // Merge for pivot column names
    MergeLevel = Table.CombineColumns(Table.TransformColumnTypes(AddLevel, {{"Level", type text}}, "de-DE"),{"Merge", "Level"},Combiner.CombineTextByDelimiter("", QuoteStyle.None),"Level" as text),
// New step: Remove dups
    #"Removed Duplicates" = Table.Distinct(MergeLevel, {"NodeKey", "ParentKey", "HierarchyPath", "Level"}),
// Create dynamic number of level-columns by pivoting
    #"Pivoted Column1" = Table.Pivot(#"Removed Duplicates", List.Distinct(#"Removed Duplicates"[Level]), "Level", "LevelColumnName")
in
    #"Pivoted Column1"

Imke Feldmann (The BIccountant)

If you liked my solution, please give it a thumbs up. And if I did answer your question, please mark this post as a solution. Thanks!

How to integrate M-code into your solution -- How to get your questions answered quickly -- How to provide sample data -- Check out more PBI- learning resources here -- Performance Tipps for M-queries

@ImkeF - I have tried changing the counter < 2, still it is taking very long time to load. Not sure why. Any idea what could have gone wrong? Thanks!

ImkeF
Community Champion
Community Champion

Hi @akhilduvvuru ,
I have change the code in the thread above. Please try again.

Imke Feldmann (The BIccountant)

If you liked my solution, please give it a thumbs up. And if I did answer your question, please mark this post as a solution. Thanks!

How to integrate M-code into your solution -- How to get your questions answered quickly -- How to provide sample data -- Check out more PBI- learning resources here -- Performance Tipps for M-queries

@ImkeF - Thanks for your quick response. There are multiple codes available here. May I know which one you corrected?

 

I used this one and it is loading for ages. Thanks!

(TableName, ParentColumnName as text, ChildColumnName as text) =>

let

// Prepare input data
    ParChTable = TableName,
    #"Renamed Columns1" = Table.RenameColumns(ParChTable,{{ChildColumnName, "NodeKey"}, {ParentColumnName, "ParentKey"}}),
    Custom1 = List.Difference(List.Distinct(#"Renamed Columns1"[ParentKey]), List.Distinct(#"Renamed Columns1"[NodeKey])),
    #"Converted to Table" = Table.FromList(Custom1, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "NodeKey"}}, MissingField.Ignore),
    #"Appended Query" = Table.Combine({#"Renamed Columns", #"Renamed Columns1"}),
    Name = Table.AddColumn(#"Appended Query", "Name", each "Item" & Text.From([NodeKey])),
    InputTable = Table.Buffer(Table.AddIndexColumn(Name, "Index", 0, 1)),
    ChildKey = "NodeKey",
    ParentKey = "ParentKey",
    LevelColumnName = "Name",

// Retrieve all parents per row
    fnAllParents = Table.AddColumn(InputTable, "AllParents", each List.Generate(()=>
    [Parent=Record.Field(_, ParentKey)],
    each [Parent] <> null and [Parent] <> "",
    each [ Parent = Table.Column(Table.SelectRows(InputTable, (ParChTable) => Record.Field(ParChTable, ChildKey) = [Parent] ), ParentKey){0} ],
    each [Parent])),
// Calculate Max Browse Depth as parameter
    MaxBrowseDepth = List.Max(List.Transform(fnAllParents[AllParents], each List.Count(_)))+1,
// Collect and sort all items for PathItems
    PathItems = Table.AddColumn(fnAllParents, "PathItems", each List.Union({List.Sort([AllParents]), {Record.Field(_, ChildKey)}})),
// Hierarchy Depth of current row
    HierarchyDepth = Table.AddColumn(PathItems, "HierarchyDepth", each List.Count([AllParents])+1),
// Check if is leaf
    Leaf = Table.AddColumn(HierarchyDepth, "IsLeaf", each if [HierarchyDepth]=MaxBrowseDepth then true else false),
// Create String Hiearchy Path (PathItems equivalent)
    HierarchyPath = Table.AddColumn(Leaf, "HierarchyPath", each Text.Combine(List.Transform([PathItems], each Text.From(_)), "|")),
// Create table for pivoting levels
    PivotTable = Table.AddColumn(HierarchyPath, "PivotTable", each Table.AddIndexColumn(Table.FromColumns({List.Union({[PathItems], List.Repeat({List.Last([PathItems])}, MaxBrowseDepth-[HierarchyDepth]+1)})}), "Level",1,1)),
// Expand pivot-level table
    #"Expanded PivotTable" = Table.ExpandTableColumn(PivotTable, "PivotTable", {"Column1", "Level"}, {"Column1", "Level"}),
// Lookup values from the name column for the level-pivots
    MergeForAccountName = Table.NestedJoin(#"Expanded PivotTable",{"Column1"},InputTable,{ChildKey},"NewColumn",JoinKind.LeftOuter),
// Expand name column
    ExpandAccountname = Table.ExpandTableColumn(MergeForAccountName, "NewColumn", {LevelColumnName}, {"LevelColumnName"}),
// Cleanup
    #"Removed Columns" = Table.RemoveColumns(ExpandAccountname,{"Column1", "AllParents", "PathItems"}),
// Create helper column for pivot column names
    AddLevel = Table.AddColumn(#"Removed Columns", "Merge", each "Level "),
    // Merge for pivot column names
    MergeLevel = Table.CombineColumns(Table.TransformColumnTypes(AddLevel, {{"Level", type text}}, "de-DE"),{"Merge", "Level"},Combiner.CombineTextByDelimiter("", QuoteStyle.None),"Level" as text),
// New step: Remove dups
    #"Removed Duplicates" = Table.Distinct(MergeLevel, {"NodeKey", "ParentKey", "HierarchyPath", "Level"}),
// Create dynamic number of level-columns by pivoting
    #"Pivoted Column1" = Table.Pivot(#"Removed Duplicates", List.Distinct(#"Removed Duplicates"[Level]), "Level", "LevelColumnName")
in
    #"Pivoted Column1"

 

akhilduvvuru
Helper IV
Helper IV

@ImkeF 
Hi, I have a similar requirement where I have multiple parents for the same child. I followed your process explained above.
However, I'm getting the below error. Can you please help me with the same? Thanks!!

An error occurred in the '' query. Expression.Error: The column 'Column1' of the table wasn't found.Details:
    Column1

 

ImkeF
Community Champion
Community Champion

Hi mim,

could you please give an example 🙂

Imke Feldmann (The BIccountant)

If you liked my solution, please give it a thumbs up. And if I did answer your question, please mark this post as a solution. Thanks!

How to integrate M-code into your solution -- How to get your questions answered quickly -- How to provide sample data -- Check out more PBI- learning resources here -- Performance Tipps for M-queries

i choose 1 as an example, the formula will check if 1 belong to the path

ImkeF
Community Champion
Community Champion

Hi mim,

this is a variation of my pattern to dynamically flatten parent-child-hierarchies. I've twitched it a bit to cover multiple parents as well. Cannot see any flaws at the moment, but you'd do me a favour to test it thoroughly. Would like to write a post for this forum here, if it works successfully, as I think that this would be useful for others as well 🙂

 

(TableName, ParentColumnName as text, ChildColumnName as text) =>

let

// Prepare input data
    ParChTable = TableName,
    #"Renamed Columns1" = Table.RenameColumns(ParChTable,{{ChildColumnName, "NodeKey"}, {ParentColumnName, "ParentKey"}}),
    Custom1 = List.Difference(List.Distinct(#"Renamed Columns1"[ParentKey]), List.Distinct(#"Renamed Columns1"[NodeKey])),
    #"Converted to Table" = Table.FromList(Custom1, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "NodeKey"}}),
    #"Appended Query" = Table.Combine({#"Renamed Columns", #"Renamed Columns1"}),
    Name = Table.AddColumn(#"Appended Query", "Name", each "Item" & Text.From([NodeKey])),
    InputTable = Table.AddIndexColumn(Name, "Index", 0, 1),
    ChildKey = "NodeKey",
    ParentKey = "ParentKey",
    LevelColumnName = "Name",

// Retrieve all parents per row
    fnAllParents = Table.AddColumn(InputTable, "AllParents", each List.Generate(()=>
    [Parent=Record.Field(_, ParentKey)],
    each [Parent] <> null and [Parent] <> "",
    each [ Parent = Table.Column(Table.SelectRows(InputTable, (ParChTable) => Record.Field(ParChTable, ChildKey) = [Parent] ), ParentKey){0} ],
    each [Parent])),
// Calculate Max Browse Depth as parameter
    MaxBrowseDepth = List.Max(List.Transform(fnAllParents[AllParents], each List.Count(_)))+1,
// Collect and sort all items for PathItems
    PathItems = Table.AddColumn(fnAllParents, "PathItems", each List.Union({List.Sort([AllParents]), {Record.Field(_, ChildKey)}})),
// Hierarchy Depth of current row
    HierarchyDepth = Table.AddColumn(PathItems, "HierarchyDepth", each List.Count([AllParents])+1),
// Check if is leaf
    Leaf = Table.AddColumn(HierarchyDepth, "IsLeaf", each if [HierarchyDepth]=MaxBrowseDepth then true else false),
// Create String Hiearchy Path (PathItems equivalent)
    HierarchyPath = Table.AddColumn(Leaf, "HierarchyPath", each Text.Combine(List.Transform([PathItems], each Text.From(_)), "|")),
// Create table for pivoting levels
    PivotTable = Table.AddColumn(HierarchyPath, "PivotTable", each Table.AddIndexColumn(Table.FromColumns({List.Union({[PathItems], List.Repeat({List.Last([PathItems])}, MaxBrowseDepth-[HierarchyDepth]+1)})}), "Level",1,1)),
// Expand pivot-level table
    #"Expanded PivotTable" = Table.ExpandTableColumn(PivotTable, "PivotTable", {"Column1", "Level"}, {"Column1", "Level"}),
// Lookup values from the name column for the level-pivots
    MergeForAccountName = Table.NestedJoin(#"Expanded PivotTable",{"Column1"},InputTable,{ChildKey},"NewColumn",JoinKind.LeftOuter),
// Expand name column
    ExpandAccountname = Table.ExpandTableColumn(MergeForAccountName, "NewColumn", {LevelColumnName}, {"LevelColumnName"}),
// Cleanup
    #"Removed Columns" = Table.RemoveColumns(ExpandAccountname,{"Column1", "AllParents", "PathItems"}),
// Create helper column for pivot column names
    AddLevel = Table.AddColumn(#"Removed Columns", "Merge", each "Level "),
    // Merge for pivot column names
    MergeLevel = Table.CombineColumns(Table.TransformColumnTypes(AddLevel, {{"Level", type text}}, "de-DE"),{"Merge", "Level"},Combiner.CombineTextByDelimiter("", QuoteStyle.None),"Level" as text),
// New step: Remove dups
    #"Removed Duplicates" = Table.Distinct(MergeLevel, {"NodeKey", "ParentKey", "HierarchyPath", "Level"}),
// Create dynamic number of level-columns by pivoting
    #"Pivoted Column1" = Table.Pivot(#"Removed Duplicates", List.Distinct(#"Removed Duplicates"[Level]), "Level", "LevelColumnName")
in
    #"Pivoted Column1"

 

Link to file: https://www.dropbox.com/s/pqaxcy4e35t6oe5/DynamicPCHierarchy.pbix?dl=0 

Imke Feldmann (The BIccountant)

If you liked my solution, please give it a thumbs up. And if I did answer your question, please mark this post as a solution. Thanks!

How to integrate M-code into your solution -- How to get your questions answered quickly -- How to provide sample data -- Check out more PBI- learning resources here -- Performance Tipps for M-queries

Imke

 

it works beautifully, but for a big datasets, the runtime increase very quickly. thanks again for your insight as usual.  

ImkeF
Community Champion
Community Champion

That's no surprise, because I forgot the buffer. Pls check with large data again:

 

(TableName, ParentColumnName as text, ChildColumnName as text) =>

let

// Prepare input data
    ParChTable = TableName,
    #"Renamed Columns1" = Table.RenameColumns(ParChTable,{{ChildColumnName, "NodeKey"}, {ParentColumnName, "ParentKey"}}),
    Custom1 = List.Difference(List.Distinct(#"Renamed Columns1"[ParentKey]), List.Distinct(#"Renamed Columns1"[NodeKey])),
    #"Converted to Table" = Table.FromList(Custom1, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "NodeKey"}}, MissingField.Ignore),
    #"Appended Query" = Table.Combine({#"Renamed Columns", #"Renamed Columns1"}),
    Name = Table.AddColumn(#"Appended Query", "Name", each "Item" & Text.From([NodeKey])),
    InputTable = Table.Buffer(Table.AddIndexColumn(Name, "Index", 0, 1)),
    ChildKey = "NodeKey",
    ParentKey = "ParentKey",
    LevelColumnName = "Name",

// Retrieve all parents per row
    fnAllParents = Table.AddColumn(InputTable, "AllParents", each List.Generate(()=>
    [Parent=Record.Field(_, ParentKey)],
    each [Parent] <> null and [Parent] <> "",
    each [ Parent = Table.Column(Table.SelectRows(InputTable, (ParChTable) => Record.Field(ParChTable, ChildKey) = [Parent] ), ParentKey){0} ],
    each [Parent])),
// Calculate Max Browse Depth as parameter
    MaxBrowseDepth = List.Max(List.Transform(fnAllParents[AllParents], each List.Count(_)))+1,
// Collect and sort all items for PathItems
    PathItems = Table.AddColumn(fnAllParents, "PathItems", each List.Union({List.Sort([AllParents]), {Record.Field(_, ChildKey)}})),
// Hierarchy Depth of current row
    HierarchyDepth = Table.AddColumn(PathItems, "HierarchyDepth", each List.Count([AllParents])+1),
// Check if is leaf
    Leaf = Table.AddColumn(HierarchyDepth, "IsLeaf", each if [HierarchyDepth]=MaxBrowseDepth then true else false),
// Create String Hiearchy Path (PathItems equivalent)
    HierarchyPath = Table.AddColumn(Leaf, "HierarchyPath", each Text.Combine(List.Transform([PathItems], each Text.From(_)), "|")),
// Create table for pivoting levels
    PivotTable = Table.AddColumn(HierarchyPath, "PivotTable", each Table.AddIndexColumn(Table.FromColumns({List.Union({[PathItems], List.Repeat({List.Last([PathItems])}, MaxBrowseDepth-[HierarchyDepth]+1)})}), "Level",1,1)),
// Expand pivot-level table
    #"Expanded PivotTable" = Table.ExpandTableColumn(PivotTable, "PivotTable", {"Column1", "Level"}, {"Column1", "Level"}),
// Lookup values from the name column for the level-pivots
    MergeForAccountName = Table.NestedJoin(#"Expanded PivotTable",{"Column1"},InputTable,{ChildKey},"NewColumn",JoinKind.LeftOuter),
// Expand name column
    ExpandAccountname = Table.ExpandTableColumn(MergeForAccountName, "NewColumn", {LevelColumnName}, {"LevelColumnName"}),
// Cleanup
    #"Removed Columns" = Table.RemoveColumns(ExpandAccountname,{"Column1", "AllParents", "PathItems"}),
// Create helper column for pivot column names
    AddLevel = Table.AddColumn(#"Removed Columns", "Merge", each "Level "),
    // Merge for pivot column names
    MergeLevel = Table.CombineColumns(Table.TransformColumnTypes(AddLevel, {{"Level", type text}}, "de-DE"),{"Merge", "Level"},Combiner.CombineTextByDelimiter("", QuoteStyle.None),"Level" as text),
// New step: Remove dups
    #"Removed Duplicates" = Table.Distinct(MergeLevel, {"NodeKey", "ParentKey", "HierarchyPath", "Level"}),
// Create dynamic number of level-columns by pivoting
    #"Pivoted Column1" = Table.Pivot(#"Removed Duplicates", List.Distinct(#"Removed Duplicates"[Level]), "Level", "LevelColumnName")
in
    #"Pivoted Column1"

 

Imke Feldmann (The BIccountant)

If you liked my solution, please give it a thumbs up. And if I did answer your question, please mark this post as a solution. Thanks!

How to integrate M-code into your solution -- How to get your questions answered quickly -- How to provide sample data -- Check out more PBI- learning resources here -- Performance Tipps for M-queries

Hi @ImkeF, thanks for sharing. Just tested your query and it shows shows some inconsistenies for some rows. Where parent is a child.
Cheers.
MМ12.png

all I can say is you know your stuff, thanks 

Helpful resources

Announcements
Join our Fabric User Panel

Join our Fabric User Panel

This is your chance to engage directly with the engineering team behind Fabric and Power BI. Share your experiences and shape the future.

June 2025 Power BI Update Carousel

Power BI Monthly Update - June 2025

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

June 2025 community update carousel

Fabric Community Update - June 2025

Find out what's new and trending in the Fabric community.