Forum Discussion
Anonymous
5 years agoNot applicable
Display Multiple level data
Hello all colleagues, I have a data like this table (SQL) When a Component has childrent, the price is zero. Level Parent Component Price 1 Computer Monitor 0 1 Computer Mouse ...
- 5 years ago
Hi Anonymous
You could start with this:
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("fZDBC4IwGMX/lbFzB91U7JiTKHIQdRQPswYJ6kTnof++fRqlqDt88Lb3Y3vvS1Ps4h1mqmp6LVsjuaoLrUA5ONut2H0nt8yLfOdKtM8tn4m8lOgU87M5EDIgZPZnwmJ0FbUsAQhXgK9Cx1ZUkCP0LBAXRT0PRCYVol5rVRvh04V3f7SqhBDhfuElohvauP7PmhQfX0XQ3HcsANx6gQWgsALXAniQYQToRmn2KhrE/1m3uJuoBow4VuxgJgitSGSGmn1mHw==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Level = _t, Parent = _t, Component = _t, Price = _t]), PreviousStep = Table.TransformColumnTypes(Source,{{"Level", Int64.Type}}), expandNames = (k, n) => List.Combine(List.Transform({n-k+1..n}, each { Text.From(_) & ".Component", Text.From(_) & ".Price" } )), joinK = (tablelist, statetable, k, n) => Table.NestedJoin(tablelist{k}, Text.From(n-k) & ".Component", statetable, Text.From(n-k+1) & ".Parent", "data", JoinKind.LeftOuter), recordNames = (rec, series) => List.Accumulate(List.RemoveFirstN(series,1), Record.Field(rec, Text.From(List.Max(series)) & ".Component"), (s, c) => s??Record.Field(rec, Text.From(c) & ".Component")), maxLevel = List.Max(PreviousStep[Level]), levels = List.Numbers(maxLevel, maxLevel, -1), tables = List.Transform(levels, (item) => Table.PrefixColumns(Table.SelectRows(PreviousStep, each [Level] = item), Text.From(item) ) ), #"Combine Levels" = List.Accumulate({1..(maxLevel-1)}, tables{0}, (statetable, c) => Table.ExpandTableColumn( joinK(tables, statetable, c, maxLevel) , "data", expandNames(c, maxLevel), expandNames(c, maxLevel))), #"Combine Prices" = Table.CombineColumns(#"Combine Levels", List.Transform(levels, each Text.From(_)&".Price"), (x) as number => Number.From(List.Max(x)), "Price"), #"Replace null Components" = Table.ReplaceValue(#"Combine Prices", null, (r) => recordNames(r, levels), Replacer.ReplaceValue, List.Transform(levels, each Text.From(_) & ".Component") ) in #"Replace null Components"To see it with your data, replace PreviousStep with your last step's name.
Best,
Spyros
Smauro
5 years agoSolution Sage
Hi Anonymous
You could start with this:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("fZDBC4IwGMX/lbFzB91U7JiTKHIQdRQPswYJ6kTnof++fRqlqDt88Lb3Y3vvS1Ps4h1mqmp6LVsjuaoLrUA5ONut2H0nt8yLfOdKtM8tn4m8lOgU87M5EDIgZPZnwmJ0FbUsAQhXgK9Cx1ZUkCP0LBAXRT0PRCYVol5rVRvh04V3f7SqhBDhfuElohvauP7PmhQfX0XQ3HcsANx6gQWgsALXAniQYQToRmn2KhrE/1m3uJuoBow4VuxgJgitSGSGmn1mHw==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Level = _t, Parent = _t, Component = _t, Price = _t]),
PreviousStep = Table.TransformColumnTypes(Source,{{"Level", Int64.Type}}),
expandNames = (k, n) => List.Combine(List.Transform({n-k+1..n}, each { Text.From(_) & ".Component", Text.From(_) & ".Price" } )),
joinK = (tablelist, statetable, k, n) => Table.NestedJoin(tablelist{k}, Text.From(n-k) & ".Component", statetable, Text.From(n-k+1) & ".Parent", "data", JoinKind.LeftOuter),
recordNames = (rec, series) => List.Accumulate(List.RemoveFirstN(series,1), Record.Field(rec, Text.From(List.Max(series)) & ".Component"), (s, c) => s??Record.Field(rec, Text.From(c) & ".Component")),
maxLevel = List.Max(PreviousStep[Level]),
levels = List.Numbers(maxLevel, maxLevel, -1),
tables = List.Transform(levels, (item) => Table.PrefixColumns(Table.SelectRows(PreviousStep, each [Level] = item), Text.From(item) ) ),
#"Combine Levels" = List.Accumulate({1..(maxLevel-1)}, tables{0}, (statetable, c) => Table.ExpandTableColumn( joinK(tables, statetable, c, maxLevel) , "data", expandNames(c, maxLevel), expandNames(c, maxLevel))),
#"Combine Prices" = Table.CombineColumns(#"Combine Levels", List.Transform(levels, each Text.From(_)&".Price"), (x) as number => Number.From(List.Max(x)), "Price"),
#"Replace null Components" = Table.ReplaceValue(#"Combine Prices", null, (r) => recordNames(r, levels), Replacer.ReplaceValue, List.Transform(levels, each Text.From(_) & ".Component") )
in
#"Replace null Components"To see it with your data, replace PreviousStep with your last step's name.
Best,
Spyros
- Anonymous5 years agoNot applicable
I think this is the answer I need. I will try it and respond the result
- Anonymous5 years agoNot applicable
I don't fully understand your code, but it's running well. Great job!