power query развернуть каталог вида: category, id, parentId в отдельные столбцы с подкатегориями, xml файл со списком родительских и вложенных категорий в одном столбце связанных по id/parentid разнести по столбцам по вложенности
Доброго дня, Возникла задача пересобрать получаемые из интернета данные в виде XML в читаемую таблицу. В xml 2 таблицы - в одной дерево каталога в виде названия,id, и родительского id, во второй товары c id категории. В итоге хочется получить таблицу с товарами и столбцами всех подкатегорий. Т.е нужно развернуть список категорий c id/parent id в отдельные столбцы и добавить к товару. Возникла мысль о Power Query. Но, так как я с PQ практически не сталкиваюсь и особо его не знаю, решать пришлось в лоб, через объединение. А потом еще сдвигать короткие цепочки. Да и число подкатегорий экспериментально только получил. Решение как бы есть, но мне не особо нравиться. Может что-нибудь более изящное кто предложит? А то самому знаний/опыта не хватает. Заодно и поучиться. Подобных задач что-то не нашел, может формулирую не правильно. Мое решение ниже и в приложенном файле. Пример xml обрезал по товарам до приемлемого и сохранил в текстовом, В оригинале в источнике ссылка api
Код
let
Источник = Xml.Tables(File.Contents("C:\...\sampleFeed.txt")){0}[shop],
category = Источник{0}[categories]{0}[category],
headrename = Table.RenameColumns(category,{{"Element:Text", "Tree"}, {"Attribute:id", "id"}, {"Attribute:parentId", "parentId"}}),
listforfilter = List.Buffer(headrename[parentId]),
tree_last = Table.SelectRows(headrename, each ([id] <> listforfilter)),
joinL1 = Table.NestedJoin(tree_last,{"parentId"},headrename,{"id"},"t1",JoinKind.LeftOuter),
#"treelast-1" = Table.ExpandTableColumn(joinL1, "t1", {"Tree", "parentId"}, {"t1.Tree", "t1.parentId"}),
joinL2 = Table.NestedJoin(#"treelast-1",{"t1.parentId"},headrename,{"id"},"t1",JoinKind.LeftOuter),
#"treelast-2" = Table.ExpandTableColumn(joinL2, "t1", {"Tree", "parentId"}, {"t1.Tree.1", "t1.parentId.1"}),
joinL3 = Table.NestedJoin(#"treelast-2",{"t1.parentId.1"},headrename,{"id"},"t1",JoinKind.LeftOuter),
#"treelast-3" = Table.ExpandTableColumn(joinL3, "t1", {"Tree"}, {"t1.Tree.2"}),
recs_temp = Table.ToRecords(Table.ReorderColumns(#"treelast-3",{"t1.Tree.2", "t1.Tree.1", "t1.Tree", "Tree", "id", "parentId", "t1.parentId", "t1.parentId.1"})),
recs_tree = List.Transform(recs_temp, each
if _[t1.Tree]=null then _&[t1.Tree.2=_[Tree], Tree = null]
else
if _[t1.Tree.1]=null then _&[t1.Tree.2=_[t1.Tree], t1.Tree.1=_[Tree], t1.Tree=null, Tree = null]
else
if _[t1.Tree.2]=null then _&[t1.Tree.2=_[t1.Tree.1], t1.Tree.1=_[t1.Tree], t1.Tree=_[Tree], Tree = null]
else _),
table_tree = Table.FromRecords(recs_tree),
offer = Источник{0}[offers]{0}[offer],
join_offer_tree = Table.NestedJoin(offer,{"categoryId"},table_tree,{"id"},"temp",JoinKind.LeftOuter),
result = Table.ExpandTableColumn(join_offer_tree, "temp", {"t1.Tree.2", "t1.Tree.1", "t1.Tree", "Tree"}, {"temp.t1.Tree.2", "temp.t1.Tree.1", "temp.t1.Tree", "temp.Tree"})
in
result
Может и к лучшему, что никто не ответил, времени заниматься не было совершенно, работает и ладно. В фильтрации конечно ошибся, но в данном наборе не принципиально, и без нее работает. Но, как время появилось, решил немного поразбираться с PQ , написал функцию для разворачивания дерева по списку записей(таблицу с добавлением индекса - в записи). функция с рекурсией
Однако, может кто-нибудь объяснить, почему в конструкции с добавлением столбца рекурсия прекрасно работает и результат в записях верный, со всеми новыми записями(столбцами) подкатегорий,
Разобрался вроде. Трансформация работает как нужно. Это, когда я пытаюсь посмотреть итог, Table.FromRecords на основе первой записи обрезает остальные столбцы. А вот как выводить все, что-то пока не понятно..
Спасибо. Разберусь, как работает, возможно интересно. А для понимания как PQ обрабатывать так и вовсе отлично, на конкретном примере. Но, пока результат явно не тот, что ожидался - веб камера в детские товары попала, а мышь в "спорт и отдых"...
Ну, товары то я обрезал в xml, там больше полумиллиона строк. А у себя на полном запустил, это нужно в xml эти id оставить. Cейчас опят занят, чуть позже попробую оставить в xml с ошибкой. cat id 215. И, по моему один уровень категорий выпал. 4 получалось, а здесь 3. Но, гораздо шустрее отработало, чем мое собственное творчество. Нужно мне с функцией разобраться, там допилю, надеюсь..
Посмотрел, что в образце исходника оставил... Ну, в общем понятно, структура столбцов в полном фиде другая. A функция вызывается по индексу столбца, а не по имени. в общем к другому столбцу привязывался вместо categoryId. С самой функцией пока не разбирался, но ошибку уже исправил . Спасибо!