При разработке отчетов в системе 1С:Предприятие 8 часто возникает ситуация, когда запрос возвращает слишком детальные данные, и строки не «сворачиваются» так, как ожидает пользователь. Особенно это актуально для конфигураций «Зарплата и управление персоналом» (ЗУП 3.1), «ERP» или «Комплексная автоматизация», где данные хранятся в разрезе документов-оснований и видов расчетных листков. Разберем подробно, как модифицировать запрос и настроить Систему компоновки данных (СКД), чтобы получить компактный отчет с группировкой по сотрудникам и выводом месяцев в колонки.
Рассмотрим исходную ситуацию. Программист пытается получить данные из регистра накопления НачисленияУдержанияПоСотрудникам. В запросе используются следующие поля:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
НАЧАЛОПЕРИОДА(НачисленияИУдержания.Период, МЕСЯЦ) КАК МесяцНачисления,
НачисленияИУдержания.Организация КАК Организация,
НачисленияИУдержания.Сотрудник КАК Сотрудник,
НачисленияИУдержания.НачислениеУдержание КАК ВидРасчета,
НачисленияИУдержания.ДокументОснование КАК ДокументОснование,
СУММА(ВЫБОР
КОГДА НачисленияИУдержания.НачислениеУдержание.КатегорияНачисленияИлиНеоплаченногоВремени = ЗНАЧЕНИЕ(Перечисление.КатегорииНачисленийИНеоплаченногоВремени.ПовременнаяОплатаТруда)
ТОГДА НачисленияИУдержания.Сумма
ИНАЧЕ 0
КОНЕЦ) КАК СуммаОклад,
СУММА(ВЫБОР
КОГДА НачисленияИУдержания.НачислениеУдержание.КатегорияНачисленияИлиНеоплаченногоВремени = ЗНАЧЕНИЕ(Перечисление.КатегорииНачисленийИНеоплаченногоВремени.Премия)
ТОГДА НачисленияИУдержания.Сумма
ИНАЧЕ 0
КОНЕЦ) КАК СуммаПремия,
СУММА(НачисленияИУдержания.Сумма) КАК Сумма
ИЗ
РегистрНакопления.НачисленияУдержанияПоСотрудникам КАК НачисленияИУдержания
ГДЕ
НачисленияИУдержания.Период МЕЖДУ &НачалоПериода И &ОкончаниеПериода
И НачисленияИУдержания.ГруппаНачисленияУдержанияВыплаты = ЗНАЧЕНИЕ(Перечисление.ГруппыНачисленияУдержанияВыплаты.Начислено)
СГРУППИРОВАТЬ ПО
НачисленияИУдержания.Организация,
НачисленияИУдержания.Сотрудник,
НачисленияИУдержания.НачислениеУдержание,
НачисленияИУдержания.ДокументОснование,
НАЧАЛОПЕРИОДА(НачисленияИУдержания.Период, МЕСЯЦ)
Основная ошибка здесь заключается в наличии полей НачислениеУдержание (ВидРасчета) и ДокументОснование в секции СГРУППИРОВАТЬ ПО. Эти поля являются уникальными для каждой записи регистра. Даже если мы хотим увидеть только общую сумму по сотруднику за месяц, наличие этих полей в группировке заставляет СУБД выводить отдельную строку для каждого вида начисления (например, отдельно «Оклад» и отдельно «Премия») и для каждого документа (например, разные приказы о премии). В итоге данные не «сворачиваются» до одной строки на сотрудника.
Для того чтобы отчет выводил данные компактно, нам необходимо исключить из запроса все поля, которые детализируют информацию глубже, чем уровень сотрудника и организации. Проанализируем, какие поля действительно нужны для формирования ресурсов, а какие только мешают группировке. Выясним причину разрастания строк: это поля ВидРасчета и ДокументОснование.
Исправленный вариант запроса будет выглядеть следующим образом:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
НАЧАЛОПЕРИОДА(НачисленияИУдержания.Период, МЕСЯЦ) КАК МесяцНачисления,
НачисленияИУдержания.Организация КАК Организация,
НачисленияИУдержания.Сотрудник КАК Сотрудник,
СУММА(ВЫБОР
КОГДА НачисленияИУдержания.НачислениеУдержание.КатегорияНачисленияИлиНеоплаченногоВремени = ЗНАЧЕНИЕ(Перечисление.КатегорииНачисленийИНеоплаченногоВремени.ПовременнаяОплатаТруда)
ТОГДА НачисленияИУдержания.Сумма
ИНАЧЕ 0
КОНЕЦ) КАК СуммаОклад,
СУММА(ВЫБОР
КОГДА НачисленияИУдержания.НачислениеУдержание.КатегорияНачисленияИлиНеоплаченногоВремени = ЗНАЧЕНИЕ(Перечисление.КатегорииНачисленийИНеоплаченногоВремени.Премия)
ТОГДА НачисленияИУдержания.Сумма
ИНАЧЕ 0
КОНЕЦ) КАК СуммаПремия,
СУММА(НачисленияИУдержания.Сумма) КАК Сумма
ИЗ
РегистрНакопления.НачисленияУдержанияПоСотрудникам КАК НачисленияИУдержания
ГДЕ
НачисленияИУдержания.Период МЕЖДУ &НачалоПериода И &ОкончаниеПериода
И НачисленияИУдержания.ГруппаНачисленияУдержанияВыплаты = ЗНАЧЕНИЕ(Перечисление.ГруппыНачисленияУдержанияВыплаты.Начислено)
СГРУППИРОВАТЬ ПО
НачисленияИУдержания.Организация,
НачисленияИУдержания.Сотрудник,
НАЧАЛОПЕРИОДА(НачисленияИУдержания.Период, МЕСЯЦ)
Обратите внимание: мы убрали лишние поля из списка выбора и из секции группировки, но сохранили логику вычисления сумм СуммаОклад и СуммаПремия через агрегатную функцию СУММА с условием ВЫБОР. Это позволяет нам получить итоги по категориям начислений, не разбивая результат на множество строк.
Для повышения производительности, особенно в крупных базах ЗУП 3.1, рекомендуется использовать виртуальную таблицу Обороты вместо физической таблицы регистра. Посмотрим на пример реализации:
ВЫБРАТЬ
НачисленияОбороты.Период КАК МесяцНачисления,
НачисленияОбороты.Организация,
НачисленияОбороты.Сотрудник,
СУММА(ВЫБОР КОГДА НачисленияОбороты.НачислениеУдержание.КатегорияНачисленияИлиНеоплаченногоВремени = &КатегорияОклад ТОГДА НачисленияОбороты.СуммаОборот ИНАЧЕ 0 КОНЕЦ) КАК СуммаОклад,
СУММА(ВЫБОР КОГДА НачисленияОбороты.НачислениеУдержание.КатегорияНачисленияИлиНеоплаченногоВремени = &КатегорияПремия ТОГДА НачисленияОбороты.СуммаОборот ИНАЧЕ 0 КОНЕЦ) КАК СуммаПремия,
СУММА(НачисленияОбороты.СуммаОборот) КАК Сумма
ИЗ
РегистрНакопления.НачисленияУдержанияПоСотрудникам.Обороты(&НачалоПериода, &КонецПериода, Месяц, ГруппаНачисленияУдержанияВыплаты = ЗНАЧЕНИЕ(Перечисление.ГруппыНачисленияУдержанияВыплаты.Начислено)) КАК НачисленияОбороты
СГРУППИРОВАТЬ ПО
НачисленияОбороты.Период,
НачисленияОбороты.Организация,
НачисленияОбороты.Сотрудник
Использование виртуальной таблицы .Обороты с периодичностью Месяц автоматически подготовит данные в нужном разрезе, а фильтрация внутри параметров виртуальной таблицы сработает быстрее, чем обычное условие ГДЕ.
После того как запрос подготовлен, переходим к настройке СКД. Это критически важный этап, без которого группировки в отчете не будут работать корректно. Разберем по шагам:
СуммаОклад, СуммаПремия и Сумма в список ресурсов.СУММА(СуммаОклад), СУММА(СуммаПремия) и СУММА(Сумма) соответственно.ЕСТЬNULL(СУММА(СуммаОклад), 0).Если поле не добавлено в ресурсы, СКД будет пытаться выводить его как обычное текстовое поле или измерение, что приведет к дублированию строк в группировках.
Чтобы реализовать требование «сотрудники в строках, месяцы в колонках», необходимо правильно настроить вкладку «Настройки» в конструкторе СКД. Вместо привычного списка (Группировка Детальные записи), мы создадим структуру типа «Таблица».
Рассмотрим последовательность действий:
Организация, а вложенную в нее — по полю Сотрудник.МесяцНачисления.СуммаОклад, СуммаПремия, Сумма.В этом случае СКД сама «развернет» данные по горизонтали. Поле МесяцНачисления будет служить заголовком колонок, а строки будут сгруппированы по сотрудникам.
Проанализируем специфику работы с регистром НачисленияУдержанияПоСотрудникам, о которой часто забывают разработчики:
1. Период регистрации vs Период действия. Поле Период в физической таблице этого регистра — это дата записи (часто дата документа). Если вы хотите построить отчет по «Месяцам начисления» (как в расчетном листке), правильнее использовать измерение ПериодРегистрации. Оно всегда кратно первому числу месяца. Если использовать Период, то начисления одного месяца могут попасть в разные дни, и функция НАЧАЛОПЕРИОДА обязательна.
2. Идентификация сотрудников. Помните, что один и тот же человек может быть уволен и принят вновь. В этом случае у него будет две разные карточки в справочнике Сотрудники. Если ваша задача — объединить все его доходы в одну строку, группируйте не по Сотруднику, а по Сотрудник.ФизическоеЛицо.
3. Группы начислений. Фильтр по ГруппыНачисленияУдержанияВыплаты.Начислено отсекает выплаты и удержания, но не забывайте, что внутри могут быть сторно-записи. Агрегатная функция СУММА корректно обработает отрицательные значения сторно, если они есть в периоде отчета.
Чтобы исправить запрос и получить корректную группировку, мы проделали следующую работу:
Такой подход гарантирует, что отчет будет информативным, быстрым и легко настраиваемым под нужды пользователя.