HR-отчёты непросто составлять. Нужно учитывать всё подряд — численность персонала, зарплату, закрытие вакансий, отработанное время, качество работы и многое другое. А ещё вычисления часто усложняются, потому что приходится учитывать нюансы трудового кодекса и особенности учёта рабочего времени.
Собрали в файле некоторые показатели для работы с HR-данными – численность сотрудников, возраст и время работы в компании. Это не столько решение по визуализации, сколько идеи для вычислений.

Исходные данные
Для оценки численности персонала потребуется справочник сотрудников и таблицы с данными по персоналу.
Справочник сотрудников

Договоры

В примере приведён упрощённый вариант данных — договоры с датами приёма и окончания работы, где с одним сотрудником заключён один договор. По факту данных обычно намного больше. Так, учитываются переводы между компаниями, ставки, причины завершения работы, изменение должностей и так далее.
* — Таблицы в файле содержат случайные записи и были созданы с применением ChatGPT.
Модель данных
В модели данных таблицы связаны по ID и датам с помощью календаря — справочника дат Date.

Договоры Contracts и справочник Employee связаны по ID сотрудника. Между таблицей дат Date и договорами Contracts созданы две связи:
- активная связь по дате старта договора;
- неактивная пунктирная связь по дате окончания договора.
Вычисления
Почти все вычисления в модели связаны с «продолжающимися процессами» Events in Progress или событиями, у которых есть даты начала и окончания. Событие считается происходящим между двумя указанными датами — в нашем примере сотрудник числится в компании в период между датой приема и датой завершения договора.

1. Принятые сотрудники
Самый простой показатель в модели – это численность принятых на работу сотрудников. Вычисления выполняются по дате старта с активной связью между таблицей дат Date и договорами Contracts.
Принято на работу = COUNTROWS ( Contracts )
2. Уволившиеся сотрудники
Для определения численности уволившихся сотрудников потребуется дата завершения договора. По этой дате между таблицами Date и Contracts создана неактивная связь, которая используется в формуле USERELATIONSHIP. У некоторых сотрудников даты окончания договора не заполнены, потому что они работают в компании в настоящее время, поэтому проверка заполненных дат выбирает только завершённые контракты.
Уволившиеся сотрудники =
CALCULATE (
COUNTROWS ( Contracts ),
USERELATIONSHIP (
Contracts[Дата окончания],
'Date'[Date] ),
NOT ( ISBLANK ( Contracts[Дата окончания] ) )
)

Формула выше считает просто число сотрудников, завершивших работу в компании. В аналитике также учитываются основание и причина увольнения — это можно сделать с помощью фильтрации по заданным критериям в формуле.

3. Численность персонала
Чтобы посчитать динамическую численность, потребуется выбор действующих в данном периоде договоров с сотрудниками, у которых дата окончания ещё не наступила или не заполнена. На практике численность уменьшается на количество сотрудников, действие договоров с которыми приостановлено.
Численность на дату =
VAR _MaxDate = MAX ( 'Date'[Date] )
VAR _EmployeeCount =
CALCULATE (
COUNTROWS ( Contracts ),
AND (
Contracts[Дата старта] <= _MaxDate,
OR ( Contracts[Дата окончания] > _MaxDate, ISBLANK ( Contracts[Дата окончания] ) )
),
ALL ( 'Date' )
)
RETURN
_EmployeeCount
Для расчета средней численности существует много разных коэффициентов, самый простой из них – по дням.
Средняя численность = AVERAGEX ( 'Date', [Численность на дату] )
При вычислении численности в таблицах с небольшими объемами данных используются просто меры, скорость работы которых анализируется для разных вариантов формул и детализации визуальных элементов с помощью меню Оптимизация → Анализатор производительности. Для больших объемов данных можно настраивать «таблицы-снимки», о которых подробнее написано в статье Марко Руссо и Альберто Феррари.
4. Группировка сотрудников
Диаграммы с характеристиками персонала тоже должны быть динамическими, то есть пересчитываться по сотрудникам, работавшим в выбранном периоде. Для группировки по возрасту потребуется таблица с названиями групп и столбцами min и max – наименьшим и наибольшим возрастом сотрудников в этой группе, как на рисунке справа.

Формула определяет число сотрудников, входящих в каждую возрастную группу. С её помощью можно построить, например, диаграмму-торнадо.
AgeGroup =
CALCULATE (
[Численность на дату],
FILTER (
VALUES ( Employee[ID] ),
[Возраст] >= MIN ( AgeGroups[min] )
&& [Возраст] <= MAX ( AgeGroups[max] )
)
)




