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

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

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

Разберем детально, почему компоновщик отсекает секции запроса и какие инструменты позволяют управлять этим поведением.

Причины исключения таблиц и вложенных запросов генератором СКД

Проанализируем механизм работы платформы при компоновке запроса. Генератор СКД выполняет автоматическую оптимизацию текста запроса перед отправкой в СУБД:

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

Способ 1. Установка признака обязательности для полей набора данных

Рассмотрим самый простой способ заставить СКД гарантированно выполнять расчет вложенных данных:

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

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

Способ 2. Настройка обязательности таблиц в конструкторе запроса

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

  1. Открываем конструктор запроса набора данных.
  2. Переходим на вкладку Компоновка данных, затем на подвкладку Таблицы.
  3. Для таблицы регистра или вложенного запроса включаем признак Обязательная.

В тексте запроса это убирает фигурные скобки {} вокруг секции ЛЕВОЕ СОЕДИНЕНИЕ, делая его безусловным для СУБД при любых вариантах настроек компоновщика.

Способ 3. Переход на пакет запросов с временными таблицами

Разберем более надежный с точки зрения производительности и оптимизации подход. Вместо глубоких вложенных запросов в секции ИЗ рекомендуется использовать пакетные запросы с сохранением промежуточных итогов во временную таблицу:


ВЫБРАТЬ
    ВыручкаИСебестоимость.АналитикаУчетаПоНоменклатуре.Партнер КАК Партнер,
    СУММА(ВыручкаИСебестоимость.СуммаВыручки) КАК СуммаВыручкиИтог
ПОМЕСТИТЬ ВТ_ИтогиПродаж
ИЗ
    РегистрНакопления.ВыручкаИСебестоимостьПродаж КАК ВыручкаИСебестоимость
СГРУППИРОВАТЬ ПО
    ВыручкаИСебестоимость.АналитикаУчетаПоНоменклатуре.Партнер
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СпрПартнеры.Ссылка КАК Партнер,
    ЕСТЬNULL(ВТ_ИтогиПродаж.СуммаВыручкиИтог, 0) КАК СуммаВыручки
ИЗ
    Справочник.Партнеры КАК СпрПартнеры
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ИтогиПродаж КАК ВТ_ИтогиПродаж
        ПО СпрПартнеры.Ссылка = ВТ_ИтогиПродаж.Партнер

Использование временных таблиц упрощает анализ структуры для СКД, делает план выполнения в СУБД более предсказуемым и гарантирует корректную предварительную агрегацию данных до основного соединения.

Способ 4. Использование связей между наборами данных СКД

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

  1. Создаем первый набор данных-запрос Партнеры, выбирающий данные из справочника Справочник.Партнеры.
  2. Создаем второй независимый набор данных-запрос Продажи, агрегирующий итоги по регистру с отбором по партнеру.
  3. Переходим на вкладку Связи наборов данных и связываем источник Партнеры с приемником Продажи по полю Партнер.

В этом случае объединение данных и расчет итогов берет на себя процессор компоновки, что полностью предотвращает дублирование строк и некорректное исключение условий при программном формировании отчетов и сегментов.

← На главную