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

Power BI is turning 10! Let’s celebrate together with dataviz contests, interactive sessions, and giveaways. Register now.

Reply
MagikJukas
Resolver III
Resolver III

Merge table in loop

Hello,

assuming I have a table like this:

FatherSon
AB
BC
CD
DE
EF
FG
GH

 

 

I would like to merge this table to obtain:

FatherSon
AB
AC
AD
AE
AF
AG
AH
BC
BD
BE
BF
BG
BH

...

 

 

how can it be achieved?

 

thanks

1 ACCEPTED SOLUTION
AlienSx
Super User
Super User

let
    Source = your_table,
    rec = Record.FromList(Source[Son], Source[Father]), 
    back_to_back = (s, name) => 
        [next_name = Record.FieldOrDefault(rec, name),
        next = if next_name is null then s else @back_to_back(s & {next_name}, next_name)][next],
    add_col = Table.AddColumn(Table.RemoveColumns(Source, {"Son"}), "Son", (x) => back_to_back({}, x[Father])),
    expand = Table.ExpandListColumn(add_col, "Son")
in
    expand

View solution in original post

6 REPLIES 6
PwerQueryKees
Super User
Super User

I adapted a function I already had. Not as slick as @AlienSx ...

 

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    getParents = (SourceTable as table, CurrentRecord as record, KeyFieldName as text, ParentFieldName as text) => 
        let 
            Parents = Table.SelectRows(SourceTable, each Record.Field(_, KeyFieldName) = Record.Field(CurrentRecord, ParentFieldName))
        in
            if Table.RowCount(Parents) = 1 then // multiple parents not allowed!
                let
                    parent = Parents{0}
                in
                    Table.Combine({@getParents(SourceTable, parent, KeyFieldName, ParentFieldName),Parents}) 
            else 
                Table.FromRecords({})
        ,
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Father", type text}, {"Son", type text}}),
    #"Added Custom" = Table.AddColumn(#"Changed Type", "Fathers", each List.Combine({{[Father]},try getParents(#"Changed Type", _, "Son", "Father")[Father] otherwise {}})),
    #"Expanded Fathers1" = Table.ExpandListColumn(#"Added Custom", "Fathers")
in
    #"Expanded Fathers1"
AlienSx
Super User
Super User

let
    Source = your_table,
    rec = Record.FromList(Source[Son], Source[Father]), 
    back_to_back = (s, name) => 
        [next_name = Record.FieldOrDefault(rec, name),
        next = if next_name is null then s else @back_to_back(s & {next_name}, next_name)][next],
    add_col = Table.AddColumn(Table.RemoveColumns(Source, {"Son"}), "Son", (x) => back_to_back({}, x[Father])),
    expand = Table.ExpandListColumn(add_col, "Son")
in
    expand
ZhangKun
Super User
Super User

let
    data = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("HcZJDQAwDAMwLnmXxNZrHKryp7EoH8szODBcrA01uOZcaMGlllxpxbXW3MPuBw==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Father = _t, Son = _t]), 
    recData = Record.FromList(data[Son], data[Father]), 
    result = 
        Table.FromRows(
            List.Combine(
                List.Transform(
                    data[Father], 
                    (f) => 
                    let 
                        a = 
                            List.Generate(
                                () => f, 
                                each not(Record.FieldOrDefault(recData, _, null) is null), 
                                each Record.FieldOrDefault(recData, _), 
                                each Record.FieldOrDefault(recData, _)
                            ), 
                        b = List.Zip({List.Repeat({f}, List.Count(a)), a})
                    in 
                        b
                )
            ), 
            Table.ColumnNames(data)
        )
in
    result

AlienSx's answer was so concise and brilliant, it gave me some inspiration to make the code less complicated

let
    data = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("HcZJDQAwDAMwLnmXxNZrHKryp7EoH8szODBcrA01uOZcaMGlllxpxbXW3MPuBw==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Father = _t, Son = _t]), 
    recData = Record.FromList(data[Son], data[Father]), 
    fx = (v) =>
        List.Generate(
            () => v, 
            each not(Record.FieldOrDefault(recData, _, null) is null), 
            each Record.FieldOrDefault(recData, _), 
            each Record.FieldOrDefault(recData, _)
        ), 
    result = 
        Table.ExpandListColumn(
            Table.AddColumn(
                data[[Father]], 
                "Son", 
                each fx([Father])
            ), 
            "Son"
        )
in
    result

 

PwerQueryKees
Super User
Super User

Am I interpreting this correctly: A row in the result table means: The father is the father, grand father or grand grand father etc. of the son? Otherwise it would just be a carthesian product of the table with itself...

I'll have a look if I can solve this...

You can solve it manually, by keeping on merging Father with Son, Son1,Son 2,... until you get null results.

then you can pivot the columns and you have it.

 

the problem is that it is not dynamic. if there number of sons changes, you will have to update the query accordingly.

thanks for your engagement @PwerQueryKees 

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.

Top Solution Authors