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