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