Страницы: 1
RSS
DAX определение среднего кол-ва работающих сотрудников в день внутри группы, Оптимизация группировки через SUMMARIZE
 
Приветствую, друзья, столкнулся с проблемой:
Есть задача:
Определить среднее кол-во работающих в день сотрудников в группе "Начинающий"
Я  делаю это конструкцией:
Код
Мера 1:=AVERAGEX(
            SUMMARIZE(
                     Filter(
                        'Таблица1';'Таблица1'[Группа]="Начинающий");
            'Таблица1'[Дата];'Таблица1'[Группа];"new"; DISTINCTCOUNT('Таблица1'[Фаимлия]))
      ;[new])

Но если кол-во строк в модели  много (в моем случае больше миллиона) и кол-во мер на основе данной конструкции не один десяток, то расчеты производятся достаточно долго.
Я знаю, что SUMMARIZE  достаточно медленно работает в части формирования расчетных столбцов внутри себя, но как можно изменить данную конструкцию, чтобы увеличить скорость расчетов?
Была мысль попробовать через GROUPBY - но в нее в качестве функций для расчетных столбцов можно встраивать только итерационные функции, то есть DISTINCTCOUNT  туда не пойдет.

Буду благодарен за помощь.
Пример прикладываю:
Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!
 
Dyroff, у Вас, как говорится, все сделано по науке. Мне кажется, что только Андрей VG или Максим З. могут как-нибудь по хитрому попробовать ускорить меру. Я же могу предложить костыль! Логика следующая, надо сделать расчет среднего без создания виртуальной таблицы. Для этого я создал доп. столбец в исходнике через функцию сцепить. Сделал два расчета через CALCULATE и поделил их между собой. К сожалению у меня нет DAX studio, поэтому не могу сопоставить скорость мер. Но в теории должно быть быстрее, так как нет виртуальной таблицы. Огромный минус метода - файл потяжелеет сразу в своих объемах из-за доп. столбца.
 
Vladimir Chebykin, Спасибо за вариант, это, конечно выход с точки зрения быстродействия, но утяжеление файла будет критичным, так как файл постоянно растет.
Буду надеяться, что Максим или Андрей зайдут:)
Вам- спасибо за уделенное время и рабочий вариант.
Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!
 
Попробовал вот такой вариант:
Код
Мера 2:=AVERAGEX(
            ADDCOLUMNS(
                     SUMMARIZE(
                           Filter(
                              'Таблица1';'Таблица1'[Группа]="Начинающий");
                                  'Таблица1'[Дата];'Таблица1'[Группа]);
            "new"; 
               CALCULATE(
                     DISTINCTCOUNT('Таблица1'[Фаимлия])
                    )
              );
      [new])


То есть вывел формирование агрегационного столбца из SUMMARIZE  в ADDCOLUMNS. По ощущениям стало быстрее.
Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!
 
Эту конструкцию здесь уже неоднократно здесь предлагал Максим Зеленский.
В PBI для ускорения таких расчетов существует функция SUMMARIZECOLUMNS. По ссылке там есть конструкт, который по сути из себя представляет эта функция и который можно повторить в PowerPivot экселя. Можете попробовать эту конструкцию применить и заценить скорость.
Скрытый текст
Вот горшок пустой, он предмет простой...
 
PooHkrd, Спасибо за статью! Много нового узнал. Обязательно попробую.

UPD
Попробовал применить, в несколько раз быстрее. Круто, спасибо!
Изменено: Dyroff - 08.11.2019 19:09:47
Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!
 
Цитата
Dyroff написал:
Круто, спасибо!
Вы же вроде не жадный.  ;) Поделитесь тогда уж с другими страждущими готовым решением на вашем примере.
Изменено: PooHkrd - 11.11.2019 10:43:00
Вот горшок пустой, он предмет простой...
 
PooHkrd, Да, конечно:)


Код
_Ср кол-во :=
AVERAGEX (
    FILTER (
        SUMMARIZE (
            CROSSJOIN (
                VALUES ( 'Таблица1'[Дата] );
                VALUES ( 'Таблица1'[Группа] )
            );
            'Таблица1'[Дата];
            'Таблица1'[Группа];
            "new"; DISTINCTCOUNT ( 'Таблица1'[Фаимлия] )
        );
        'Таблица1'[Группа] = "Начинающий"
    );
    [new]
)
Изменено: Dyroff - 25.03.2020 17:10:47
Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!
 
Спасибо!

А если столбцов группировок больше чем один? В примере предложенная формула уже не срабатывает
 
Raritet, Вам же в этой теме ответили:)

Чуть-чуть подумать и значения филиала поменять на декартово произведение филиалов, должностей и тд?
Код
AltNorm:=VAR dataTbl =
    ADDCOLUMNS (
        CROSSJOIN ( VALUES ( 'Таблица1'[Филиал] ); VALUES ( 'Таблица1'[Должность] ) );
        "altNorm";
            MIN (
                CALCULATE ( SUM ( 'Таблица1'[Значение] ); 'Таблица1'[Категория] = "Текущее количество" );
                CALCULATE ( SUM ( 'Таблица1'[Значение] ); 'Таблица1'[Категория] = "Норма" )
            )
    )
VAR result =
    SUMX ( dataTbl; [altNorm] )
RETURN
    result
 
Цитата
surkenny написал:
Raritet , Вам же в  этой теме  ответили:)
Да, я просто запутался )) Пытался найти похожие варианты решения, и не туда ответ написал ))
 
Доброе время суток
Цитата
surkenny написал:
CROSSJOIN
А каков смысл в CROSSJOIN? Чем
Код
SUMMARIZE('Таблица1'; 'Таблица1'[Филиал]; 'Таблица1'[Должность])
Зачем нужно декартовое произведение?
 
Андрей VG, , можно, конечно:)
Я имел ввиду, что Raritet мог догадаться по аналогии с мерами из темы.
А SUMMARIZE быстрее отработает?
 
Цитата
surkenny написал:
А SUMMARIZE быстрее отработает?
В рамках создания строкового контекста - так же. В некоторых случаях, будет быстрее, чем CROSSJOIN - зависит от того, какое реальное сужение подмножества от CROSSJOIN получается при SUMMARIZE.
Страницы: 1
Наверх