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