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