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