Страницы: 1
RSS
PQ Накопительный итог
 
Добрый день.
Не могу найти где ошибка, в примере нужно посчитать накопительный итог.
Поправьте, пожалуйста
Благодарю.
 
Mirdv, поправлять, пожалуй не буду. При всем уважении к Кен Пульсу, вариант расчета он дал, мягко говоря не оптимальный по быстродействию (зато полукнопочный!), а ковыряться где вы там еще и накосячили вообще нет желания.
Зато поделюсь вариантом от местного старожила Андрей VG, добрый человек с год назад кому-то тут помог такой функцией (я её слегка только переделал для удобства использования):
Код
let
    FnRunSum = (sub as table, sort as text, col as text)=>
        let
            setRunningOrder = Table.Sort( sub, {{sort, Order.Ascending}} ),
            itemCount = Table.RowCount( sub ),
            sumList = List.Buffer( Table.ToColumns( Table.SelectColumns( setRunningOrder, {col}) ){0} ),
            calcRunningTotal = List.Generate(
                () => [id = 0, runningSum = sumList{id}],
                each [id] < itemCount,
                each [id = [id] + 1, runningSum = [runningSum] + sumList{id}],
                each {[id], [runningSum]}
            ),
            makeRunningTable = Table.FromRows( calcRunningTotal, {"id", "runningSum"} ),
            addIdxForRunningJoin = Table.AddIndexColumn( setRunningOrder, "id"),
            result = Table.Join( addIdxForRunningJoin, {"id"}, makeRunningTable, {"id"} )
        in
            result,

    Source = Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content],
    ChangedType = Table.TransformColumnTypes(Source,{{"Date", type date}, {"Sale", Int64.Type}}),
    Custom1 = FnRunSum( ChangedType, "Date", "Sale" )
in
    Custom1
Изменено: PooHkrd - 07.06.2019 15:51:56
Вот горшок пустой, он предмет простой...
 
PooHkrd, благодарю за код
Учусь.
Разбирать более менее получается код, когда не используется
в коде функция и то бывают нюансы, которые сильно стопорят
Принцип, как разбирать код с функциями пока не понятен.

Посмотрел и сохранил себе как заготовку. Пока все(
Изменено: Mirdv - 07.06.2019 16:24:31
 
Mirdv, да ладно, чего там непонятного?

Код
let
    FnRunSum = (sub as table, sort as text, col as text)=> /*Получаем в функцию таблицу, 
название столбца, по которому нужно сделать сортировку, и название столбца, по которому нужна, собственно, сумма.*/
        let
            setRunningOrder = Table.Sort( sub, {{sort, Order.Ascending}} ), //сортируем
            itemCount = Table.RowCount( sub ), //считаем количество элементов списка
            sumList = List.Buffer( Table.ToColumns( Table.SelectColumns( setRunningOrder, {col}) ){0} ),      /*выбираем нужный столбец 
и помещаем его в буфер */
            calcRunningTotal = List.Generate(             // самое интересное - генерим список записей с индексом и накоплением
                () => [id = 0, runningSum = sumList{id}],
                each [id] < itemCount,
                each [id = [id] + 1, runningSum = [runningSum] + sumList{id}],
                each {[id], [runningSum]}
            ),
            makeRunningTable = Table.FromRows( calcRunningTotal, {"id", "runningSum"} ),  //из списка создаем новую таблицу
            addIdxForRunningJoin = Table.AddIndexColumn( setRunningOrder, "id"),    /* берем таблицу, которая получилась после сортировки 
в начале функции и добавляем к ней столбец с индексами */
            result = Table.Join( addIdxForRunningJoin, {"id"}, makeRunningTable, {"id"} ) // джойним к этой таблице сгенерированный столбец с накоплением 
        in
            result,  //ПРОФИТ!
 
    Source = Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content],
    ChangedType = Table.TransformColumnTypes(Source,{{"Date", type date}, {"Sale", Int64.Type}}),
    Custom1 = FnRunSum( ChangedType, "Date", "Sale" )
in
    Custom1
Изменено: PooHkrd - 07.06.2019 17:07:22
Вот горшок пустой, он предмет простой...
 
PooHkrd, благодарю за ваши комментарии к коду
Конечно так намного проще разбирать код и понять логику построения кода
 
Добрый день.
Нашел на просторах Интернет еще вариант
Самое простое решение на мой взгляд
 
Доброе время суток
Цитата
Mirdv написал:
Самое простое решение на мой взгляд
Сравните тысяч этак на 20 строк алгоритмы :)  
Простота - она порой...
 
Mirdv, с точки зрения реализации - да. На массиве 20к строк этот простой алгоритм отработал за 6 минут 33 секунды. Алгоритм на List.Generate за 1 секунду. 1кк строк за 26 секунд, "Простой" алгоритм я на таком массиве даже запускать боюсь.  ;)
Вот вам примерчик - можете поэкспериментировать.
Смысл в том, что формируется единый список на основании котрого List.Generate за один проход делает готовый результа, который остается только сцепить с исходной таблицей. В "простом" алгоритме вы обрабатывает такое количество таблиц, сколько строк в массиве, т.е. для 20к строк вы 20 тыс раз обсчитываете огромную таблицу, а с List.Generate  только один раз + 1 джойн.
Изменено: PooHkrd - 26.06.2019 09:47:03
Вот горшок пустой, он предмет простой...
 
Цитата
PooHkrd написал:
+ 1 джойн
Алексей, был вариант и без join ;)
 
Андрей VG, думаю не суть как исходной таблице приклеить получившийся результат, главное что результат формируется за один проход по всем строкам таблицы.
Вот горшок пустой, он предмет простой...
 
Всем здравия.
PooHkrd, очень точно замечено "с точки зрения реализации"
За комментарий как работают алгоритмы благодарствую.

P.s.
Я обучаюсь PQ здесь на форуме на чужих примерах.
Комментариев в примерах не много, а спецам итак все понятно
Прошу прощения мне не всегда все сразу понятно, хотя в примере все просто и очевидно.
И ясно почему, потому что уже готово и главное работает.
Но процесс освоения не стоит на месте, пусть и идет не так быстро, как это получается у других.
 
Цитата
Mirdv написал:
Но процесс освоения не стоит на месте
Ну, тогда дополнительный материал от тёзки для изучения. Посмотрим, будет ли понятно :)
 
Андрей VG, благодарю за новый вариант
Все что я пока могу, это разобрать как работает запрос до момента появления функции.
Честно говоря, первый раз встречаю запрос без последовательных шагов  - "одним куском".
Посмотрел путем создания пустого запроса и копированием каждый раз новой строки из запроса в примере, но только до момента когда появляется первая функция
Разобрать или переделать функцию обратно в запрос пока не могу.
Сохранил в копилку как рабочее решение

P.s. Может кто встречал пояснение как функцию из запроса переделать в запрос (извините за каламбур) или всем итак ясно, кроме меня конечно же :)
Power Query Formula Language Specification - про это в курсе, ковыряю насколько позволяют знания Англ )
Изменено: Mirdv - 26.06.2019 16:40:27
 
Цитата
Андрей VG написал:
 дополнительный материал  от тёзки
Не самый удачный пример, ибо запрос медленный
Переписал дабы ускорить
Код
let
    Source        = Table.TransformColumnTypes(Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content],{{"День", type date},{"Час", type time}}),
    Filter        = Table.SelectRows(Source,each [#"Накопительный Т_1 (час)"]<>null),
    Filter1       = Table.SelectRows(Source, each [#"Накопительный Т_1 (час)"]=null)[[День],[Час],[T_1],[N_1]],
    GroupByDate   = Table.Buffer(Table.Group(Filter1, {"День"}, {{"a", each _, type table},{"b",each List.Sum([T_1])}})),
    f1=(a)        =>List.Buffer(List.Generate(()=>[i=0,v=a{0}],each [i] < List.Count(a),each [i=[i]+1,v=[v]+a{i}],each [v])),
    f2=(t)=>let
        rec       = Cumulatively{[День=t[День]{0}]},
        a         = f1(List.Buffer(t[T_1])),
        b         = List.Zip(List.Reverse(((a)=>List.Zip({a,{rec[b]}}))(List.Reverse(a)))),
        c         = Table.FromColumns(Table.ToColumns(t)&b,Table.ColumnNames(Source))
    in Table.RemoveColumns(c,{"День"}),
    Cumulatively  = Table.FromColumns(List.RemoveLastN(Table.ToColumns(GroupByDate),1)&{f1(GroupByDate[b])},Table.ColumnNames(GroupByDate)),
    Cumulatively1 = Table.ExpandTableColumn(Table.TransformColumns(Cumulatively,{{"a",f2}}), "a", List.Skip(Table.ColumnNames(Source),1))
in
    if Table.RowCount(Filter1)>0 then Table.Combine({Filter,Table.RemoveColumns(Cumulatively1,{"b"})}) else Source
Изменено: Андрей Лящук - 26.06.2019 20:31:22
 
Андрей Лящук,
-благодарю за ваш вариант
Страницы: 1
Наверх