Функция process
Функция process
используется для расширенного агрегирования и заключается в другую агрегатную функцию. Она вычисляет диапазон значений выражения по указанному измерению или измерениям. Схожа с запросом GROUP BY
в SQL.
Используется только в формулах разрезов и мер.
При вычислении функция process
разворачивается в агрегирующий подзапрос, результат выполнения которого присоединяется к основному запросу через join
. В случае отсутствия колонок разреза подзапрос помещается в секцию основного запроса.
При вычислении функции process
в подзапрос добавляется фильтрация основного запроса, которая не содержит формул с этой функцией. Фильтрация применяется следующим образом:
- Формируется последовательность таблиц, необходимых для вычисления результата функции
process
- В этой последовательности осуществляется поиск таблиц, в которых находятся колонки разреза
- Каждая из этих таблиц в последовательности заменяется на подзапрос с фильтрацией
Синтаксис
process({агрегирующее выражение}, колонка разреза)
— функция вычисляет агрегирующее выражение по колонке разреза:
агрегирующее выражение
— может содержать любое агрегирующее выражение + колонки + константы + переменные (вводимое значение, вычисляемое значение, статический список, динамический список)колонка разреза
— содержит колонку разреза, может отсутствовать
Особенности функции process
:
- Если для расчета используются только показатели
process({guid}_measure)
и{dimension_column}
, то вместоt1 join t2
используется сразуt2
- Работает автозамена
{dimension_column}
для уменьшения количества связей- Пример 1:
process(sum(log.revenue), case_table.case_id)
использует данные двух таблиц. Так как есть связьcase_table.case_id
иlog.case_id
, будет использоваться только таблицаlog
. Компонентcase_table
связывается с таблицейprocess
по колонкеcase_table.case_id = log.case_id
, потому что это заменяемые колонки - Пример 2:
process(sum(log.revenue), case_table.type)
использует данные двух таблиц. Сначала свяжутся данные таблицы, потом происходит расчет агрегации с группировкой поcase_table.type
, далее таблицаcase_table
по левой связи с результатом по колонкеtype
- Пример 1:
- Если второй параметр не указан, считается общая агрегация. Чтобы посчитать долю, введите следующее:
x / process (sum(x))
- Если имеется несколько функций
process
с одним разрезом, запрос объединяется
Использование функции process
внутри функции process
может привести к некорректному отображению результата или ошибке.
- Функция работает только с одной колонкой разреза. Невозможно использовать несколько колонок разреза.
- В качестве колонки разреза не рекомендуется использовать поле из той же таблицы, откуда агрегируются данные. Используйте поле из связанной таблицы-справочника, где поле группировки есть в одном экземпляре. В противном случае может произойти умножение данных, и результат будет некорректным.
Ненаправленные связи
Связь N:M — это связь между двумя таблицами, когда одному значению из первой таблицы соответствует множество значений из второй таблицы и одному значению из второй таблицы соответствует множество значений из первой таблицы. Таким образом, связь является ненаправленной.
При добавлении связей в модель данных связи N:M учитываются как обычные связи, когда проверяется, что между двумя таблицами может существовать лишь один путь по связям.
Применение:
При фильтрации учитываются как обычные связи, по которым формируются цепочки подзапросов.
При построении последовательности учитываются только при обработке функции process
. Обработка агрегатной части функции process
учитывает только обычные связи, связей N:M она не видит. Таблицы колонок из секции разреза функции process
могут добавляться в последовательность через связи N:M. При этом сначала в последовательность добавляется максимально возможное количество таблиц по обычным связям. Оставшиеся таблицы добавляются по обычным связям и связям N:M. Для связей N:M также работает замена колонок.
Примеры использования функции process
Для примеров используем таблицы с данными о событиях процесса, в которых указаны идентификатор кейса (case_id
), время события (event_time
) и название события (event_name
).
Расчет длительности процесса
Функция определяет минимальное и максимальное значение времени статусов для каждого экземпляра со своим case_id
, после чего находит разницу между этими значениями в секундах:
process(date_diff('second', min("event_log"."event_time"), max("event_log"."event_time")), "case_table"."case_id")
Расчет длительности между этапами
Функция определяет минимальное значение времени для первого статуса Заказ готовится и максимальное значение времени для второго статуса Заказ передан курьеру для каждого экземпляра со своим case_id
, после чего находит разницу между этими значениями в секундах:
process(if((argMaxIf(toUnixTimestamp("event_log"."event_time"), "event_log"."event_time", "event_log"."event_name" = 'Заказ передан курьеру') - argMinIf(toUnixTimestamp("event_log"."event_time"), "event_log"."event_time", "event_log"."event_name" = 'Заказ готовится') as duration)>0, duration, 0), ("case_table"."case_id"))
Сценарии протекания процесса
Функция сортирует по времени статусы для каждого case_id
, и формирует текст, в котором каждый статус выводится на отдельной строке:
process(arrayStringConcat(arraySort((x,y)-> y, groupArray("event_log"."event_name"), groupArray("event_log"."event_time")),'\r\n'),("case_table"."case_id"))
Наличие перехода в определенном случае
Функция проверяет, есть ли среди статусов каждого case_id
хотя бы один целевой статус, в нашем случае — Ожидается передача курьеру:
if(process(countIf("event_log"."event_name", "event_log"."event_name" like 'Ожидается передача курьеру')>0, ("case_table"."case_id")), 'Есть "Ожидается передача курьеру"', 'Нет "Ожидается передача курьеру"')
Разбиение на группы по условию
Функция вычисляет длительность для каждого case_id
из таблицы event_log
и распределяет их по категориям в зависимости от длительности:
multiIf(process(date_diff('second', min("event_log"."event_time"), max("event_log"."event_time")), "case_table"."case_id") as duration < 30*60, 'Менее 30 минут', duration<60*60, 'от 30 мин до 1 часа', duration<2*60*60, 'от 1 до 2 часов', 'Более 2 часов')
Была ли статья полезна?