Условие
Из подключённой Google Sheets-таблицы построить в Power BI:
1. Таблица активности клиентов (matrix). Строки — месяц. Столбцы:
- Потенциальные: не совершали покупок (этап ≠ «Оплата получена»).
- Новые: первый раз купили в этом месяце.
- Активные: купили в этом месяце + в последние X дней совершили ≥ 2 покупок.
- Пассивные: купили в этом месяце + в X дней совершили 1 покупку.
- Вернувшиеся: купили в этом месяце + в X дней не совершали покупок.
- Потерянные: не совершали покупок последние X дней.
X — параметр-срез от 7 до 60.
2. Воронка конверсии по этапам сделки (visual Funnel).
3. Матрицы суммы товаров по типу активности и среднее число дней на этап.
Запреты: новые столбцы и таблицы в Power Query запрещены, считаем через DAX. Слайсеры по менеджеру и товару.
Решение
Подход
Все вычисления — через DAX-меры, а не calculated columns. Слайсер X через What-if параметр.
DAX-меры
-- Параметр X (создаётся через "Modeling → New Parameter")
X = SELECTEDVALUE('X Parameter'[X], 30)
-- Дата текущего месяца контекста
CurrMonth = SELECTEDVALUE(Calendar[Month])
CurrMonthStart = STARTOFMONTH(LASTDATE(Calendar[Date]))
CurrMonthEnd = ENDOFMONTH(LASTDATE(Calendar[Date]))
-- Был ли клиент в "Оплата получена" в текущем месяце
IsBuyerThisMonth(client) =
CALCULATE(
DISTINCTCOUNT(Сделки[ИДсделки]),
Этапы[Этапсделки] = "4. Оплата получена",
Этапы[Датаэтапа] >= [CurrMonthStart],
Этапы[Датаэтапа] <= [CurrMonthEnd]
)
-- Кол-во клиентов с >=2 покупок за X дней до начала текущего месяца
ActiveClients =
COUNTROWS(
FILTER(
SUMMARIZE(Сделки, Сделки[ФИОклиента]),
[IsBuyerThisMonth] >= 1
&&
CALCULATE(
DISTINCTCOUNT(Этапы[ИДсделки]),
Этапы[Этапсделки] = "4. Оплата получена",
Этапы[Датаэтапа] >= [CurrMonthStart] - [X],
Этапы[Датаэтапа] < [CurrMonthStart]
) >= 2
)
)Логика классификации
Для каждого клиента в текущем месяце:
IF не было покупок ever → Потенциальный
ELSE IF первая покупка в этом месяце → Новый
ELSE
IF купил в этом месяце:
IF в [m-X, m) ≥ 2 покупок → Активный
IF в [m-X, m) = 1 покупка → Пассивный
IF в [m-X, m) = 0 покупок → Вернувшийся
ELSE
IF не покупал последние X дней → Потерянный
Воронка
Этапы должны быть отсортированы:
- Лид
- КП выставлено
- КП согласовано
- Оплата получена
- Товар отправлен
- Товар доставлен
- Сделка завершена
Хитрость: в данных некоторые сделки пропускают этапы. Но фактически проходят все. Нужно «достроить» недостающие — для воронки взять для каждой сделки максимальный достигнутый этап, и считать сделку как прошедшую все нижние этапы.
MaxStage =
MAXX(
RELATEDTABLE(Этапы),
VALUE(LEFT(Этапы[Этапсделки], 1))
)
ConversionAt(stage) =
DIVIDE(
CALCULATE(DISTINCTCOUNT(Сделки[ИДсделки]), Сделки[MaxStage] >= stage),
CALCULATE(DISTINCTCOUNT(Сделки[ИДсделки]), Сделки[MaxStage] >= 1)
)Матрица среднего времени на этап
AvgDaysOnStage =
AVERAGEX(
Сделки,
CALCULATE(
MIN(Этапы[Датаэтапа], Этапы[Этапсделки] = currstage)
-
MIN(Этапы[Датаэтапа], Этапы[Этапсделки] = prevstage)
)
)Слайсеры
Менеджер— из таблицы Сделки.Название товара— из таблицы Товар.X— what-if параметр.
Подводные камни
- What-if параметр X в Power BI создаёт disconnected table. Любые ссылки на X должны идти через
SELECTEDVALUE. - «Активный» и «Новый» взаимоисключаются: новый ≠ активный (нет prev покупок). В коде сначала проверка на «новый».
- Этапы сделки в данных пропущены, но фактически пройдены — нужно либо «достроить» через MAX(stage), либо при funnel считать «пройдено если max ≥ stage».
- Datatime in Excel-serial (44558) — нужно конвертировать в DAX через
DATE(1899,12,30)+44558. - Слайсер «Менеджер» работает на Сделки, но не на Этапы напрямую — нужны связи.
- Производительность DAX: SUMMARIZE с FILTER на тысячах клиентов может быть медленным. Используйте
KEEPFILTERSи измерения вместо calculated columns.
Эталонный ответ
DAX-меры с CALCULATE+FILTER по интервалам относительно CurrMonthStart. Параметр X через What-if. Воронка — MaxStage per deal + cumulative count. Слайсеры на Менеджера, Товар, X.