Почему в СКД пропадают поля и группировки при изменении запроса и как это исправить?

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

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

Проанализируем причины такого поведения платформы 1С:Предприятие и разберем по шагам, как восстановить корректный вывод данных.

Причины исключения полей компоновщиком СКД

В отличие от простого выполнения запроса через объект Запрос, СКД не выполняет переданный текст «как есть». Перед отправкой в СУБД встроенный механизм — КомпоновщикМакетаКомпоновкиДанных — полностью перестраивает исходный текст с учетом настроек варианта, выбранных полей, отборов и доступных метаданных.

Выделим основные причины, почему поле (например, Организация) исключается из результата:

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

Способ 1. Явное приведение типа через функцию ВЫРАЗИТЬ

Рассмотрим самый надежный способ устранения неопределенности типа при разыменовании реквизитов через ссылку. Если данные выбираются из табличной части документа, необходимо явно указать тип для поля шапки:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
    ГрафикОтпусковСотрудники.Ссылка.Дата КАК Период,
    ГрафикОтпусковСотрудники.Сотрудник КАК Сотрудник,
    ГрафикОтпусковСотрудники.ДатаНачала КАК ДатаНачала,
    ГрафикОтпусковСотрудники.ДатаОкончания КАК ДатаОкончания,
    ГрафикОтпусковСотрудники.КоличествоДней КАК КоличествоДней,
    ГрафикОтпусковСотрудники.ВидОтпуска КАК ВидОтпуска,
    ДАТАВРЕМЯ(1, 1, 1) КАК ПеренесеннаяДатаНачала,
    ЛОЖЬ КАК Перенесен,
    ВЫРАЗИТЬ(ГрафикОтпусковСотрудники.Ссылка.Организация КАК Справочник.Организации) КАК Организация,
    ГрафикОтпусковСотрудники.Ссылка КАК ДокументПланирования,
    ЗНАЧЕНИЕ(Документ.ГрафикОтпусков.ПустаяСсылка) КАК ДокументПереноса
ПОМЕСТИТЬ ВТСотрудники
ИЗ
    Документ.ГрафикОтпусков.Сотрудники КАК ГрафикОтпусковСотрудники
ГДЕ
    ГрафикОтпусковСотрудники.Ссылка = &ГрафикОтпусковСсылка
    И НЕ ГрафикОтпусковСотрудники.Ссылка.ПометкаУдаления

Использование конструкции ВЫРАЗИТЬ(... КАК Справочник.Организации) гарантирует, что генератор макета СКД однозначно определит состав доступных полей и связей для группировки.

Способ 2. Установка признака «Обязательное» в роли поля набора данных

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

  1. Откроем схему компоновки данных и перейдем на вкладку Наборы данных.
  2. В табличной части со списком полей найдем нужное поле (например, Организация).
  3. В колонке Роль откроем окно настройки роли поля.
  4. Установим флаг Обязательное.

Флаг Обязательное указывает компоновщику макета, что поле должно присутствовать в результирующем SQL-запросе всегда, независимо от того, выбрано ли оно пользователем в текущем пользовательском варианте отчета.

Способ 3. Автоматическое обновление полей набора данных

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

  1. Перейдем на закладку Наборы данных.
  2. Нажмем кнопку Автозаполнение (или удалим проблемные поля из списка и нажмем кнопку обновления полей запроса).
  3. Проверим, что для поля Организация заполнен тип данных, сняты флаги ограничения на использование в группировках, полях и отборах.

Как получить реальный текст запроса, сформированный СКД

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


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

// Перебираем наборы данных макета и получаем итоговый текст запроса
Для Каждого НаборДанных Из МакетКомпоновки.НаборыДанных Цикл
    Если ТипЗнч(НаборДанных) = Тип("НаборДанныхЗапросМакетаКомпоновкиДанных") Тогда
        ТекстРеальногоЗапроса = НаборДанных.Запрос;
    КонецЕсли;
КонецЦикла;

Анализ переменной ТекстРеальногоЗапроса позволяет наглядно увидеть, какие временные таблицы или поля были исключены платформой на этапе генерации макета.

Альтернативное решение: передача данных через внешний набор

Если структура запроса нестандартная и переопределение схемы в СКД вызывает сложности, сформируем результат в коде модуля и передадим готовую таблицу значений в СКД через Набор данных - Объект:


Запрос = Новый Запрос;
Запрос.Текст = "..."; // Текст запроса без модификаций СКД
РезультатЗапроса = Запрос.Выполнить().Выгрузить();

ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаДанных", РезультатЗапроса);

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);

Такой подход полностью исключает вмешательство оптимизатора запросов СКД в выборку данных из табличных частей и регистров.

← На главную