При разработке отчетов в конфигурации 1С:Зарплата и управление персоналом 3.1 программисты часто сталкиваются с необходимостью получить актуальное значение периодического показателя (например, оклада, тарифной ставки или процента надбавки) на определенную дату или для конкретной строки начисления. Регистр сведений ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников имеет свои особенности, которые не позволяют использовать стандартную виртуальную таблицу "СрезПоследних" в обычном понимании. Разберем подробно, почему возникают ошибки при выборке данных и как составить корректный запрос.
Рассмотрим типичную ошибку, которую совершают начинающие разработчики. При попытке получить последнюю запись через функцию МАКСИМУМ(Период), в список полей группировки часто включают и само поле Значение. Выясним причину, по которой это приводит к дублированию строк. В языке запросов 1С механизм СГРУППИРОВАТЬ ПО работает таким образом, что система ищет уникальные комбинации всех указанных полей.
Если у сотрудника показатель менялся (например, сначала был 8, а потом стал 11), то строки в базе данных будут иметь разные значения в поле Значение. Когда вы добавляете это поле в группировку, запрос вернет обе строки, так как комбинации "Значение 8 + Дата1" и "Значение 11 + Дата2" являются разными с точки зрения СУБД. Функция МАКСИМУМ просто выберет наибольшую дату для каждой из этих уникальных пар, но не отсеет старое значение.
Поскольку мы работаем с физической таблицей регистра, нам необходимо выполнить задачу в два этапа. Проанализируем ситуацию: сначала нам нужно найти момент времени, когда показатель изменился в последний раз, а уже затем узнать, какое именно значение было установлено в этот момент.
Шаг 1: Подготовка временной таблицы с максимальными датами. На этом этапе мы выбираем только ключевые измерения (Сотрудник, Показатель) и находим для них максимальный период. Обратите внимание, что поле Значение здесь использовать нельзя.
ВЫБРАТЬ
ЗначенияПоказателей.Сотрудник КАК Сотрудник,
ЗначенияПоказателей.Показатель КАК Показатель,
МАКСИМУМ(ЗначенияПоказателей.Период) КАК МаксПериод
ПОМЕСТИТЬ ВТ_МаксимальныеДаты
ИЗ
РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников КАК ЗначенияПоказателей
ГДЕ
ЗначенияПоказателей.Период <= &ПериодРегистрации
СГРУППИРОВАТЬ ПО
ЗначенияПоказателей.Сотрудник,
ЗначенияПоказателей.Показатель
;
Шаг 2: Получение значений путем соединения. Теперь мы соединяем полученную временную таблицу с исходным регистром, чтобы "подтянуть" значение показателя, соответствующее найденному периоду.
ВЫБРАТЬ
Т1.Сотрудник,
Т1.Показатель,
РегистрЗначения.Значение
ИЗ
ВТ_МаксимальныеДаты КАК Т1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников КАК РегистрЗначения
ПО Т1.Сотрудник = РегистрЗначения.Сотрудник
И Т1.Показатель = РегистрЗначения.Показатель
И Т1.МаксПериод = РегистрЗначения.Период
Сложность задачи возрастает, когда показатели нужно вывести рядом с данными о начислениях. В регистре расчета Начисления период регистрации обычно кратен месяцу, а в регистре показателей Период — это точная дата изменения (например, 15-е число месяца). Соединение "лоб в лоб" по периоду здесь не сработает.
Рассмотрим правильную логику соединения. Для каждой строки начисления нам нужно найти показатель, у которого Период меньше или равен дате начала начисления (ПериодДействияНачало). Посмотрим на пример реализации такого условия в связи таблиц:
Нужно использовать условие связи ПО Начисления.Сотрудник = Показатели.Сотрудник И Показатели.Период <= Начисления.ПериодДействияНачало. Однако такое соединение создаст "множество" строк (все исторические записи показателя до даты начисления). Чтобы оставить одну, в итоговой выборке снова придется использовать МАКСИМУМ(Показатели.Период) и группировать по всем полям начисления.
В современных конфигурациях на базе 1С:ЗУП 3.1 разработчики фирмы "1С" предусмотрели специальный механизм — виртуальные таблицы представлений. Это наиболее профессиональный и эффективный способ получения данных, так как он автоматически учитывает приоритеты документов, исправления и корректные срезы данных.
В тексте запроса используются специальные конструкции, которые программно заменяются на сложные оптимизированные запросы. Рассмотрим пример использования такого подхода для получения плановых начислений и показателей:
// В тексте запроса СКД или обработки пишем заглушку:
ВЫБРАТЬ
Представления.Сотрудник,
Представления.Показатель,
Представления.Значение
ПОМЕСТИТЬ ВТ_ДанныеПоказателей
ИЗ
Представления_ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников КАК Представления
ГДЕ
"ТолькоРазрешенные" = ИСТИНА
Чтобы этот код заработал, перед выполнением запроса в коде на языке 1С необходимо вызвать специальную процедуру:
ТекстЗапроса = СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Запрос;
ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц(ТекстЗапроса);
Этот метод позволяет избежать написания громоздких конструкций со вложенными запросами и гарантирует, что вы получите именно те цифры, которые пользователь видит в экранных формах документов "Изменение оплаты труда" или "Назначение планового начисления".
Проанализируем ситуацию с полем ДействуетДо. В рассматриваемом регистре пустое значение этой даты (01.01.0001) означает, что показатель установлен бессрочно. Если же в поле стоит конкретная дата, значит, после этого момента показатель перестает действовать (если не было новых записей). При ручном написании запросов важно учитывать:
ДействуетДо либо пустое, либо больше текущей даты.Регистратор (или МоментВремени), чтобы корректно определить последовательность изменений.Подводя итог, можно сказать: для простых отчетов используйте метод с временной таблицей МАКСИМУМ(Период), исключая значение из группировки. Для сложных архитектурных решений в рамках ЗУП 3.1 всегда отдавайте предпочтение механизму Представления_..., так как он минимизирует риск возникновения ошибок при расчете сложных схем начислений.