В процессе разработки сложных отчетов на базе Системы компоновки данных (СКД) программисты часто сталкиваются с интеллектуальным механизмом оптимизации запросов. Этот механизм призван ускорить работу отчета: если СКД видит, что какое-то поле не выбрано пользователем в настройках (не выводится в таблицу, не используется в отборах или группировках), она просто вырезает его из итогового текста запроса. Однако возникают ситуации, когда поле критически необходимо для промежуточных расчетов, правильной группировки во временных таблицах или корректного агрегирования данных, как в случае с расчетом отработанного времени по дням в табеле. Если СКД удалит поле День до того, как произойдет сворачивание данных за месяц, результат отчета будет неверным.
Разберем подробно, какими методами можно заставить СКД оставить нужное поле в запросе, не нарушая логику компоновки.
Прежде чем переходить к решениям, проанализируем ситуацию. Когда мы пишем запрос в схеме компоновки данных, мы описываем лишь "шаблон". Итоговый текст запроса, который уйдет в СУБД, формируется построителем в момент выполнения. Если ваше поле ДатаСобытия или День участвует во временной таблице для группировки, но в финальной выборке (в настройках компоновки) пользователь хочет видеть только общую сумму за месяц, СКД может решить, что группировка по дням избыточна, и удалит это поле из СГРУППИРОВАТЬ ПО и ВЫБРАТЬ во временной таблице. В итоге данные "схлопнутся" раньше времени без учета нужной аналитики.
Рассмотрим самый надежный и простой способ управления составом полей через конструктор СКД. Этот метод позволяет жестко закрепить поле за запросом.
День).Что это дает? Установка этого признака сообщает оптимизатору СКД, что данное поле должно присутствовать в тексте запроса всегда, вне зависимости от того, выбрал его пользователь в настройках или нет. Это особенно актуально для временных таблиц, где поле используется для промежуточных соединений или условий.
Проанализируем ситуацию, когда автозаполнение полей отключено или нам нужно точечно управлять выборкой внутри текста запроса. Для этого в 1С существует механизм фигурных скобок {}.
Рассмотрим пример кода в тексте запроса:
ВЫБРАТЬ
Табель.Сотрудник КАК Сотрудник,
{Табель.День КАК День},
СУММА(Табель.Часы) КАК Часы
ПОМЕСТИТЬ ВТ_ДанныеТабеля
ИЗ
РегистрНакопления.ДанныеТабеля КАК Табель
ГРУППИРОВАТЬ ПО
Табель.Сотрудник,
{Табель.День}
Помещая поле в фигурные скобки внутри секции ВЫБРАТЬ и ГРУППИРОВАТЬ ПО, мы делаем его доступным для системы компоновки, но даем ей возможность управлять его наличием. Однако, если мы хотим гарантированного присутствия, лучше комбинировать этот метод с первым способом или явно указывать поле в настройках.
Выясним причину, по которой иногда помогает изменение структуры группировки. Существует интересный нюанс работы парсера СКД: если в секции ВЫБРАТЬ полей меньше, чем в секции ГРУППИРОВАТЬ ПО, система иногда оставляет "лишние" поля группировки, чтобы не нарушать структуру запроса. Рассмотрим пример:
ВЫБРАТЬ
Данные.Сотрудник КАК Сотрудник,
СУММА(Данные.ОтработаноЧасов) КАК ОтработаноЧасов
ИЗ
ВТ_ИсходныеДанные КАК Данные
ГРУППИРОВАТЬ ПО
Данные.Сотрудник,
Данные.День
В данном случае мы выбираем только сотрудников и сумму, но группируем еще и по дням. Это заставляет СУБД сначала свернуть данные по дням, а уже потом СКД может наложить свои итоги. Однако полагаться только на этот метод рискованно, так как при включенном автозаполнении СКД может "исправить" этот запрос под свои нужды.
Если программные методы по какой-то причине недоступны (например, при работе с универсальным отчетом в облаке, где нельзя менять схему), мы можем повлиять на поведение системы через настройки самого отчета:
День (или то, которое пропадает).Это принудительно включает поле в состав запроса, даже если оно не отображается в колонках отчета.
Разберем еще один архитектурный подход. Замечено, что СКД более агрессивно оптимизирует временные таблицы (ПОМЕСТИТЬ), так как считает их структуру полностью подконтрольной. Вложенные запросы (подзапросы в секции ИЗ) оптимизируются чуть иначе. Если логика позволяет, попробуйте переписать получение данных по дням через вложенный запрос:
ВЫБРАТЬ
Итог.Сотрудник,
Итог.ВсегоЗаМесяц
ИЗ
(ВЫБРАТЬ
Внутр.Сотрудник КАК Сотрудник,
Внутр.День КАК День,
СУММА(Внутр.Часы) КАК ВсегоЗаМесяц
ИЗ
РегистрНакопления.ОтработанноеВремя КАК Внутр
ГРУППИРОВАТЬ ПО
Внутр.Сотрудник,
Внутр.День) КАК Итог
В такой структуре поле День внутри подзапроса имеет больше шансов "выжить", так как оно является частью определения источника данных Итог.
Для решения проблемы с удалением поля День в отчетах по табелю наиболее эффективным и правильным с точки зрения методологии 1С является Способ №1 (установка роли Обязательное). Это гарантирует, что поле не исчезнет ни при каких пользовательских настройках группировок, и ваши промежуточные расчеты по видам времени внутри одного дня останутся корректными.
Если вы работаете в условиях ограниченного доступа к конфигуратору (облачные решения), используйте Способ №4 через настройки "Использовать всегда". Помните, что СКД — это мощный инструмент, и понимание принципов его оптимизации позволяет создавать гибкие и точные отчеты.