Антон, спасибо за справочник! Очень нужная и удобно изложенная информация. Я вообще не программист :), но вашим справочником по DAX пользуюсь постоянно, все понятно. Удачи вашему проекту!
Я для обработки больших файлов использую Power Query, отлично справляется. Размер исходного файла не влияет на конечную сводную таблицу, если создать только подключение.
Как ни странно циклы делать можно. Через переменные создаются виртуальные таблицы через генерацию серии, что по сути и есть счётчик цикла + добавляются к исходной серии ряд столбцов, которые являются действиями по циклу, фильтром из виртуальной таблицы выдерживается значение которое мы и вычислили по сути циклом. Все три основные цикла можно реализовать через этот метод. Очень даже работает. Если тема актуальна, отпишитесь в комментарии - скину ссылку как это делается.
@@Matt-lg8zn , ссылка:community.powerbi.com/t5/Community-Blog/For-and-While-Loops-in-DAX/ba-p/636314 Правда на бусурманском языке, но это сейчас не проблема. Как я уже говорил всё сводится к созданию серии и работе внутри созданной таблицы. Я создаю в исходном запросе на данные добавить индекс строк (от 1 до номера последней) чтобы обращаться к ним в цикле по номеру индекса и однозначно идентифицировать каждую строку и работаю с этим индексом как переменной цикла. Готовые PBi скинуть не могу, так как там много секретных данных, но если не получится разобраться могу скинуть пример DAX формулы столбца с комментариями что и зачем.
@@Matt-lg8zn сразу решил отправить и пример. Проблема следующая. В исходных файлах по экономике есть номера инициатив. Под некоторыми инициативами есть ряд технических драйверов по инициативе выше. И вместо номера этой инициативы экономисты пишут "Д", мол драйвер к инициативе выше. Задача определить к какой инициативе каждый драйвер, то есть подняться по строкам выше циклом при встрече с любой "Д" и первая строка с номером инициативы будет номером для этого драйвера. Код вычисляемого столбца: Используются столбцы: 'СПП (2)'[Index] - индекс строк добавленный в исходном запросе в Power Query. Данные там расположены как в исходных данных и порядок строк сохраняется 'СПП (2)'[1] - столбец в котором находятся номера инициатив и "Д" (работаю с ними как с текстом, так как номера могут быть не очень и номерами) Код вычисляемого столбцы Цикл перебор по поиску номеров инициатив = var _n=30 'комментарий - var - это объявление переменных. Все программные штуки делаем в переменной. 'комментарий - _n=30 край по счетчику цикла. То есть я мотаю вверх на 30 ячеек в поиске номера для драйвера var _IndexNom='СПП (2)'[Index] 'комментарий - запоминаю номер индекса в текущей строке VAR __loopTable = GENERATESERIES(0,_n) 'комментарий - генерирую виртуальную таблицу в виде серии от 0 до _n=30. По сути цикл от 0 до 30 VAR __loopTable1 = ADDCOLUMNS(__loopTable,"_Nom",MAXX(FILTER('СПП (2)','СПП (2)'[Index]=_IndexNom-[Value]),IF('СПП (2)'[1]="Д",-100,IF('СПП (2)'[1]="",0,1)))) 'комментарий - добавляю к созданной серии колонку и называю её _Nom. При помощи Фильтра отматываю строки назад конструкцией "_IndexNom-[Value]", по каждой строке в зависимости от наполнения при помощи IF присваиваю значения второму столбцу, если "Д", драйвер, то -100, если пустота то 0, а если номер инициативы, который может быть как цифрой, так и цифрой с тексом, присваиваю значение 1, а MAXX который всё это обнимает, выдергиваю это значение в свою колонку которая принимает значения -100/0/1 var _min = minx(FILTER(__loopTable1,[_Nom]>0),[Value]) 'Комментарий - выдергиваю в переменную _min нужный индекс который определяю фильтром по виртуальной таблице где значения в _Nom больше нуля , то есть те кто равны 1, то есть те которые появились при встрече с номером, а так как их может быть выше по строке много, то беру самую первую встречу при помощи minx return 'комментарий - return выхожу из блока переменных с уже обработанной таблицей из которой получил переменную _min в которой содержится цифра от 0 до 30, которая указывает на сколько строк выше по индексу находится номер инициативы по которой указан драйвер в этой строке if('СПП (2)'[1]="" || ISBLANK('СПП (2)'[1]),BLANK(),CONCATENATEX(FILTER('СПП (2)','СПП (2)'[Index]=_IndexNom-_min),'СПП (2)'[1])) 'комментарий - если в этой строке столбца с номерами и драйверами "Д" пусто, то остваляю пустоту, в если не пусто то выдергиваю фильтром в текс в нужном мне столбце по однознакчной координате "IndexNom минус _min", то есть если тут номер инициативы, то показывает себя же (_min=0), а если "Д", то _min содержит количество строк до ближайшего номера инициативы вычитая его из индекса получаю индекс строки с номером инициативы. и по этому индексу и выдергиваю искомое значение. Схожим образом можно перебрать хоть все значения в любой таблице выдернув максимальный индекс в базе данных и по фильтру к ним обращаться и проводить любые операции с ними. Вариантов масса, тут всё упирается в фантазию. Код без комментариев для копирования: Цикл перебор по поиску номеров инициатив = var _n=30 var _IndexNom='СПП (2)'[Index] VAR __loopTable = GENERATESERIES(0,_n) VAR __loopTable1 = ADDCOLUMNS(__loopTable,"_Nom",MAXX(FILTER('СПП (2)','СПП (2)'[Index]=_IndexNom-[Value]),IF('СПП (2)'[1]="Д",-100,IF('СПП (2)'[1]="",0,1)))) var _min = minx(FILTER(__loopTable1,[_Nom]>0),[Value]) return if('СПП (2)'[1]="" || ISBLANK('СПП (2)'[1]),BLANK(),CONCATENATEX(FILTER('СПП (2)','СПП (2)'[Index]=_IndexNom-_min),'СПП (2)'[1]))
Антон, спасибо за справочник! Очень нужная и удобно изложенная информация. Я вообще не программист :), но вашим справочником по DAX пользуюсь постоянно, все понятно. Удачи вашему проекту!
пожалуйста, очень рад, что справочник помогает. В скором времени справочник обновится - будет еще лучше
Спасибо, что вы есть!
Пожалуйста ))
Супер. Спасибо. Справочник - дело!
Отлично, спасибо за справочник.
пожалуйста
Спасибо за мега супер справочник!!!💥🔥👍👍👍
Я несколько раз пробовала скачать справочник и всё пусто. Подумала, что это обман.
Круто! С дебютом на Ютубе. Желаю просмотров и подписчиков...хоть и тематика понятно, что узконаправленная. Удачи с каналом!
Спасибо, Павел ))
Спасибо за справочник. Я записался в вашу группу. Очень интересует понятие контекста при создании формул DAX
Пожалуйста, Николай. Контексты будем разбирать
Здравствуйте, а в power pivot может сэкономить время при обработке больших данных, в то время как эксель может зависнуть?
Я для обработки больших файлов использую Power Query, отлично справляется. Размер исходного файла не влияет на конечную сводную таблицу, если создать только подключение.
Я не одинок, после SQL кажется, что DAX нелогичный взрыв в мозгу, потом правда привыкаешь, правдо потихоньку, сильнее "потихоньку" ,ичем напримерв SQL
Получается, циклы делать нельзя? Необходимо использовать как в excel протягивание по ячейкам?
Как ни странно циклы делать можно. Через переменные создаются виртуальные таблицы через генерацию серии, что по сути и есть счётчик цикла + добавляются к исходной серии ряд столбцов, которые являются действиями по циклу, фильтром из виртуальной таблицы выдерживается значение которое мы и вычислили по сути циклом. Все три основные цикла можно реализовать через этот метод. Очень даже работает. Если тема актуальна, отпишитесь в комментарии - скину ссылку как это делается.
@@nBoomkAn тема актуальна, за ссылку благодарен!
@@Matt-lg8zn , ссылка:community.powerbi.com/t5/Community-Blog/For-and-While-Loops-in-DAX/ba-p/636314
Правда на бусурманском языке, но это сейчас не проблема. Как я уже говорил всё сводится к созданию серии и работе внутри созданной таблицы. Я создаю в исходном запросе на данные добавить индекс строк (от 1 до номера последней) чтобы обращаться к ним в цикле по номеру индекса и однозначно идентифицировать каждую строку и работаю с этим индексом как переменной цикла.
Готовые PBi скинуть не могу, так как там много секретных данных, но если не получится разобраться могу скинуть пример DAX формулы столбца с комментариями что и зачем.
@@Matt-lg8zn сразу решил отправить и пример. Проблема следующая. В исходных файлах по экономике есть номера инициатив. Под некоторыми инициативами есть ряд технических драйверов по инициативе выше. И вместо номера этой инициативы экономисты пишут "Д", мол драйвер к инициативе выше. Задача определить к какой инициативе каждый драйвер, то есть подняться по строкам выше циклом при встрече с любой "Д" и первая строка с номером инициативы будет номером для этого драйвера.
Код вычисляемого столбца:
Используются столбцы:
'СПП (2)'[Index] - индекс строк добавленный в исходном запросе в Power Query. Данные там расположены как в исходных данных и порядок строк сохраняется
'СПП (2)'[1] - столбец в котором находятся номера инициатив и "Д" (работаю с ними как с текстом, так как номера могут быть не очень и номерами)
Код вычисляемого столбцы
Цикл перебор по поиску номеров инициатив = var _n=30
'комментарий - var - это объявление переменных. Все программные штуки делаем в переменной.
'комментарий - _n=30 край по счетчику цикла. То есть я мотаю вверх на 30 ячеек в поиске номера для драйвера
var _IndexNom='СПП (2)'[Index]
'комментарий - запоминаю номер индекса в текущей строке
VAR __loopTable = GENERATESERIES(0,_n)
'комментарий - генерирую виртуальную таблицу в виде серии от 0 до _n=30. По сути цикл от 0 до 30
VAR __loopTable1 = ADDCOLUMNS(__loopTable,"_Nom",MAXX(FILTER('СПП (2)','СПП (2)'[Index]=_IndexNom-[Value]),IF('СПП (2)'[1]="Д",-100,IF('СПП (2)'[1]="",0,1))))
'комментарий - добавляю к созданной серии колонку и называю её _Nom. При помощи Фильтра отматываю строки назад конструкцией "_IndexNom-[Value]", по каждой строке в зависимости от наполнения при помощи IF присваиваю значения второму столбцу, если "Д", драйвер, то -100, если пустота то 0, а если номер инициативы, который может быть как цифрой, так и цифрой с тексом, присваиваю значение 1, а MAXX который всё это обнимает, выдергиваю это значение в свою колонку которая принимает значения -100/0/1
var _min = minx(FILTER(__loopTable1,[_Nom]>0),[Value])
'Комментарий - выдергиваю в переменную _min нужный индекс который определяю фильтром по виртуальной таблице где значения в _Nom больше нуля , то есть те кто равны 1, то есть те которые появились при встрече с номером, а так как их может быть выше по строке много, то беру самую первую встречу при помощи minx
return
'комментарий - return выхожу из блока переменных с уже обработанной таблицей из которой получил переменную _min в которой содержится цифра от 0 до 30, которая указывает на сколько строк выше по индексу находится номер инициативы по которой указан драйвер в этой строке
if('СПП (2)'[1]="" || ISBLANK('СПП (2)'[1]),BLANK(),CONCATENATEX(FILTER('СПП (2)','СПП (2)'[Index]=_IndexNom-_min),'СПП (2)'[1]))
'комментарий - если в этой строке столбца с номерами и драйверами "Д" пусто, то остваляю пустоту, в если не пусто то выдергиваю фильтром в текс в нужном мне столбце по однознакчной координате "IndexNom минус _min", то есть если тут номер инициативы, то показывает себя же (_min=0), а если "Д", то _min содержит количество строк до ближайшего номера инициативы вычитая его из индекса получаю индекс строки с номером инициативы. и по этому индексу и выдергиваю искомое значение.
Схожим образом можно перебрать хоть все значения в любой таблице выдернув максимальный индекс в базе данных и по фильтру к ним обращаться и проводить любые операции с ними. Вариантов масса, тут всё упирается в фантазию.
Код без комментариев для копирования:
Цикл перебор по поиску номеров инициатив = var _n=30
var _IndexNom='СПП (2)'[Index]
VAR __loopTable = GENERATESERIES(0,_n)
VAR __loopTable1 = ADDCOLUMNS(__loopTable,"_Nom",MAXX(FILTER('СПП (2)','СПП (2)'[Index]=_IndexNom-[Value]),IF('СПП (2)'[1]="Д",-100,IF('СПП (2)'[1]="",0,1))))
var _min = minx(FILTER(__loopTable1,[_Nom]>0),[Value])
return
if('СПП (2)'[1]="" || ISBLANK('СПП (2)'[1]),BLANK(),CONCATENATEX(FILTER('СПП (2)','СПП (2)'[Index]=_IndexNom-_min),'СПП (2)'[1]))