Почему СКД выводит пустые значения, хотя в консоли запросов данные заполнены?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на системе компоновки данных (СКД) разработчики нередко сталкиваются с ситуацией: сложный запрос с пакетами и временными таблицами в консоли запросов выполняется идеально и возвращает заполненные поля (например, статус заказа или дату изменения), но при формировании того же отчета в СКД или программном выводе в ТаблицуЗначений некоторые поля оказываются пустыми или содержат пустые ссылки. Разберем детально, почему так происходит и как исправить такое поведение.

Причина 1. Автоматическая подстановка параметров в виртуальные таблицы СКД

Проанализируем типовую ситуацию: в тексте запроса используется срез последних без явного указания даты среза:


ВЫБРАТЬ
    АТСтатусыЗаказовСрезПоследних.ЗаказПокупателя,
    ЕСТЬNULL(АТСтатусыЗаказовСрезПоследних.Статус, ЗНАЧЕНИЕ(Перечисление.АТСтатусыЗаказов.ПустаяССылка)) КАК Статус,
    ЕСТЬNULL(АТСтатусыЗаказовСрезПоследних.Период, ДАТАВРЕМЯ(1, 1, 1)) КАК Период
ПОМЕСТИТЬ ПоследниеСтатусыЗаказов
ИЗ
    РегистрСведений.АТСтатусыЗаказов.СрезПоследних(
            ,
            ЗаказПокупателя В
                (ВЫБРАТЬ РАЗЛИЧНЫЕ
                    ТаблицаЗаказов.РС_ЗаказПокупателя КАК ЗаказПокупателя
                ИЗ
                    ТаблицаЗаказов КАК ТаблицаЗаказов)) КАК АТСтатусыЗаказовСрезПоследних

Когда мы запускаем такой запрос в консоли запросов, параметр среза не заполнен, и платформа получает актуальные записи на текущий момент времени. Однако компоновщик данных ведет себя иначе. СКД анализирует структуру запроса и при обнаружении виртуальных таблиц (таких как СрезПоследних, СрезПервых, Остатки) автоматически связывает их неявные параметры со стандартными параметрами отчета (например, Период или КонецПериода).

Если в коде или настройках отчета для периода задана дата (например, граница отбора по документам), СКД передает эту дату в срез регистра сведений. Если статус заказа был изменен позже этой даты или если время даты окончания установлено в 00:00:00 (начало дня), виртуальная таблица вернет пустой результат. В итоговом запросе с помощью ЛЕВОЕ СОЕДИНЕНИЕ поле статуса примет значение NULL, которое через ЕСТЬNULL превратится в ЗНАЧЕНИЕ(Перечисление.АТСтатусыЗаказов.ПустаяСсылка).

Рассмотрим способы решения этой проблемы:

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

Причина 2. Ошибки при настройке полей-ресурсов

Выясним еще одну частую причину, из-за которой ссылочные поля и перечисления очищаются при выводе. Если поле (например, ПоследнийСтатус) ошибочно добавлено на вкладку Ресурсы схемы компоновки данных, СКД ожидает для него агрегатной функции.

Если для ссылочного поля на вкладке «Ресурсы» не задано выражение или задано выражение, которое рассчитывается только для определенных группировок, на детальных записях или в группировках без агрегации СКД вернет пустое значение. Особенно ярко это проявляется при программной выгрузке результата компоновщика в ТаблицуЗначений: строки детальных записей могут не содержать рассчитанных ресурсов.

Решение проблемы с ресурсами:

  1. Если статус или дата должны отображаться на уровне группировок, явно пропишите агрегатную функцию на вкладке «Ресурсы», например: Максимум(ПоследнийСтатус)
  2. Если агрегировать статус не требуется, удалите поле из списка ресурсов. Выводите его как обычное реквизитное поле группировки или детальных записей.

Причина 3. Разграничение прав доступа (RLS)

Проанализируем контекст выполнения. Консоль запросов разработчики часто запускают под полными правами администратора. Реальный отчет пользователи формируют в рабочей среде с включенными ограничениями прав на уровне записей (RLS). Если у роли пользователя нет прав на чтение регистра сведений или связанных документов, левое соединение не найдет строк, и поле перечисления вернет пустую ссылку.

Для проверки этой гипотезы запустите консоль запросов от имени пользователя с ограниченными правами либо выполните запрос в привилегированном режиме.

Диагностика: как увидеть реальный запрос СКД

Чтобы точно узнать, с какими условиями СКД выполняет запрос к базе данных, посмотрим на реальный макет компоновки в отладчике. Для этого используем КомпоновщикМакетаКомпоновкиДанных:


КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки);

// В переменной ТекстРеальногоЗапроса будет содержаться итоговый SQL-подобный запрос 
// со всеми подставленными отборами и параметрами виртуальных таблиц:
ТекстРеальногоЗапроса = МакетКомпоновки.НаборыДанных.НаборДанных1.Запрос;

Проверив ТекстРеальногоЗапроса и значения в коллекции КомпоновщикНастроек.Настройки.ПараметрыДанных, вы сразу увидите, какие параметры периода СКД неявно подставила в срез регистра, и сможете быстро устранить расхождение.

← На главную