При построении кадровых отчетов часто возникает задача проанализировать количественный состав сотрудников не просто на текущую дату, а в динамике по месяцам. Типовая сложность заключается в том, что в течение выбранного периода (например, года) сотруднику может исполниться полное количество лет, переводящее его из одной возрастной категории в другую. Рассмотрим, как реализовать такой отчет в Системе компоновки данных (СКД), чтобы возраст рассчитывался корректно на конец каждого месяца, а не на общую дату окончания периода.
Разберем ситуацию на примере: если сотруднику исполняется 20 лет в декабре, то в колонках отчета с января по ноябрь он должен учитываться в группе "до 20 лет", а в колонке декабря — уже в группе "от 20 до 30 лет". Если мы будем рассчитывать возраст просто на дату окончания периода отчета, мы получим статичную картину, которая не отражает реальное состояние дел в прошлых месяцах.
Для решения этой задачи нам необходимо выполнить три основных условия:
В языке запросов 1С нет встроенной функции, которая возвращает таблицу дат. Поэтому мы создадим виртуальную таблицу месяцев. Проанализируем способ создания такой шкалы через соединение системных таблиц или выборку из производственного календаря. Если производственный календарь не заполнен, можно использовать универсальный запрос для генерации чисел.
Пример запроса для получения месяцев периода:
ВЫБРАТЬ
ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Цифры.Номер) КАК МесяцПериода,
КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Цифры.Номер), МЕСЯЦ) КАК КонецМесяца
ПОМЕСТИТЬ ВТ_Периоды
ИЗ
(ВЫБРАТЬ 0 КАК Номер ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 2
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 5
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 8
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 9 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 10 ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 11) КАК Цифры
ГДЕ
ДОБАВИТЬКДАТЕ(&ДатаНачала, МЕСЯЦ, Цифры.Номер) <= &ДатаОкончания
;
Проанализируем формулу расчета возраста. Использование конструкции ГОД(Дата1) - ГОД(Дата2) часто дает ошибку, так как не учитывает, наступил ли уже день рождения в текущем году. Рассмотрим более точную формулу, которую мы применим в соединении с нашей таблицей периодов.
Основной запрос будет выглядеть следующим образом:
ВЫБРАТЬ
ВТ_Периоды.МесяцПериода КАК ПериодМесяц,
Сотрудники.Ссылка КАК Сотрудник,
Сотрудники.ДатаРождения КАК ДатаРождения,
РАЗНОСТЬДАТ(Сотрудники.ДатаРождения, ВТ_Периоды.КонецМесяца, ГОД) -
(ВЫБОР
КОГДА ДОБАВИТЬКДАТЕ(Сотрудники.ДатаРождения, ГОД, РАЗНОСТЬДАТ(Сотрудники.ДатаРождения, ВТ_Периоды.КонецМесяца, ГОД)) > ВТ_Периоды.КонецМесяца
ТОГДА 1
ИНАЧЕ 0
КОНЕЦ) КАК ВозрастНаКонецМесяца
ПОМЕСТИТЬ ВТ_СотрудникиСВозрастом
ИЗ
ВТ_Периоды КАК ВТ_Периоды
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
ПО (Сотрудники.ДатаРождения <= ВТ_Периоды.КонецМесяца)
// Здесь можно добавить условие на работу сотрудника в этом месяце (КадроваяИстория)
;
Выясним причину, почему жесткое прописывание условий ВЫБОР КОГДА непосредственно в запросе может быть неудобным. Если требования к интервалам изменятся (например, группа "от 20 до 30" превратится в "от 18 до 25"), придется переписывать весь запрос. Однако для простого отчета воспользуемся классической схемой группировки:
ВЫБРАТЬ
Данные.ПериодМесяц,
Данные.Сотрудник,
ВЫБОР
КОГДА Данные.ВозрастНаКонецМесяца < 20 ТОГДА "Менее 20 лет"
КОГДА Данные.ВозрастНаКонецМесяца МЕЖДУ 20 И 30 ТОГДА "От 20 до 30 лет"
КОГДА Данные.ВозрастНаКонецМесяца МЕЖДУ 31 И 40 ТОГДА "От 31 до 40 лет"
КОГДА Данные.ВозрастНаКонецМесяца МЕЖДУ 41 И 50 ТОГДА "От 41 до 50 лет"
ИНАЧЕ "Свыше 50 лет"
КОНЕЦ КАК ВозрастнаяГруппа
ИЗ
ВТ_СотрудникиСВозрастом КАК Данные
Чтобы отчет выглядел наглядно (в строках — группы, в колонках — месяцы), выполним следующие настройки в схеме компоновки данных:
ПериодМесяц на закладке "Наборы данных" установим роль Период и укажем тип "Дополнительный период". Это позволит СКД правильно сортировать месяцы и выводить их в хронологическом порядке.Количество(Сотрудник). Это обеспечит подсчет людей в каждой ячейке таблицы.ВозрастнаяГруппа.ПериодМесяц.Рассмотрим подробнее нюанс, связанный с актуальностью данных. В реальных базах данных (например, 1С:ЗУП) недостаточно просто выбрать сотрудников из справочника. Необходимо учитывать:
КонецМесяца. Для этого нужно использовать левое соединение с виртуальной таблицей КадроваяИсторияСотрудников.СрезПоследних или физической таблицей регистра.Таким образом, мы получили динамическую модель, которая пересчитывает возрастную категорию каждого человека для каждой временной отсечки. Это позволяет увидеть реальную демографическую картину предприятия в динамике.