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

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

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

Разберем причину проблемы: механизм «Раздувания» запроса (Join Explosion)

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

Проанализируем ситуацию: если мы пишем ДокументОснование.Контрагент, платформа на уровне СУБД создает LEFT JOIN со всеми таблицами, которые входят в этот составной тип. Если типов 20 — будет 20 соединений. Если же мы добавляем «вторую точку» (обращаемся к реквизиту через еще одно составное поле), количество соединений начинает расти в геометрической прогрессии. Чтобы защитить систему от критического падения производительности и перегрузки SQL-сервера, СКД автоматически «отсекает» такие сложные пути, делая поля недоступными для пользователя в настройках отчета.

Способ 1: Использование оператора ВЫРАЗИТЬ (Рекомендуемый метод)

Самый правильный и эффективный способ вернуть пропавшие поля — это явно указать платформе, к какому типу данных мы обращаемся. Это снимает неопределенность и избавляет SQL-запрос от лишних соединений. Рассмотрим, как преобразить проблемный запрос.

Вместо прямого обращения:

ПриобретениеТоваровУслугТовары.ЗаказПоставщику.ДокументОснование.Контрагент

Мы должны использовать конструкцию ВЫРАЗИТЬ. Проанализируем пример кода:


ВЫБРАТЬ
    ПриобретениеТоваровУслугТовары.Номенклатура КАК Номенклатура,
    ВЫРАЗИТЬ(ПриобретениеТоваровУслугТовары.ЗаказПоставщику.ДокументОснование КАК Документ.ЗаказКлиента).Контрагент КАК Контрагент
ИЗ
    Документ.ПриобретениеТоваровУслуг.Товары КАК ПриобретениеТоваровУслугТовары

Важный нюанс: Если ДокументОснование может содержать несколько разных типов документов, у которых есть реквизит Контрагент, нам придется либо выбрать один наиболее вероятный тип, либо использовать конструкцию ВЫБОР КОГДА ССЫЛКА. Однако в большинстве практических задач приведение к конкретному типу через ВЫРАЗИТЬ мгновенно делает поле доступным в дереве СКД.

Способ 2: Использование временных таблиц (ВТ)

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

Разберем по шагам, как это реализовать:

  1. Создаем первый запрос в пакете, который выбирает ссылку на составное поле и помещает ее во временную таблицу.
  2. Во втором запросе пакета соединяем эту временную таблицу с конкретной таблицей документа (например, Документ.ЗаказПоставщику).
  3. Выбираем реквизиты уже из прямой таблицы документа.

Пример структуры такого запроса:


ВЫБРАТЬ
    Товары.ЗаказПоставщику КАК Заказ
ПОМЕСТИТЬ ВТ_Данные
ИЗ
    Документ.ПриобретениеТоваровУслуг.Товары КАК Товары;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Данные.Заказ,
    ЗаказПоставщику.ДокументОснование.Контрагент КАК Контрагент
ИЗ
    ВТ_Данные КАК ВТ_Данные
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказПоставщику КАК ЗаказПоставщику
    ПО ВТ_Данные.Заказ = ЗаказПоставщику.Ссылка

Способ 3: Настройка типов значений и ролей в наборе данных

Иногда проблема кроется не в самом запросе, а в том, как СКД интерпретирует полученные поля. Выясним, что можно подправить в визуальном конструкторе схемы компоновки данных на закладке «Наборы данных»:

Проверка колонки «Тип значения»: Найдите ваше поле в списке. Если там указан «Составной тип», попробуйте нажать на кнопку выбора типа и вручную ограничить список только теми типами, которые реально могут встретиться в этом поле. Часто после ручного ограничения типов СКД «прозревает» и позволяет разыменовывать ссылки.

Проверка ограничений поля: Убедитесь, что в колонках «Ограничение поля», «Ограничение условия» и «Ограничение группировки» не стоят флажки. Иногда платформа ошибочно устанавливает их для сложных путей.

Роли полей: Если вы используете связь наборов данных или сложные вложенные запросы, попробуйте явно указать роль поля. Это подскажет СКД, как правильно строить дерево доступных полей.

Способ 4: Оптимизация условий ГДЕ и работа с NULL

Проанализируем интересную особенность платформы 8.3.16 и выше. В сообщениях форума упоминалось, что использование условия НЕ ... ЕСТЬ NULL для составных полей может сбивать оптимизатор СКД. Если вы используете условие:


ГДЕ НЕ ПриобретениеТоваровУслугТовары.ЗаказПоставщику.ДокументОснование ЕСТЬ NULL

СКД может решить, что тип этого поля неопределен, и заблокирует доступ к вложенным свойствам.

Рекомендация: Замените проверку на NULL проверкой на пустую ссылку конкретного типа или используйте оператор ССЫЛКА. Это сделает запрос более прозрачным для системы компоновки.

Способ 5: Флаг «Автозаполнение» и псевдонимы

Рассмотрим ситуацию, когда в схеме снят флаг «Автозаполнение». В этом случае каждое поле, к которому вы хотите получить доступ (включая те, что идут через точку), должно быть явно описано в секции ВЫБРАТЬ и иметь понятный псевдоним. Если псевдонимы дублируются или не заданы, СКД может исключить «сложное» поле из списка выбора, считая его служебным или избыточным.

Всегда старайтесь давать полям через две точки осмысленные уникальные имена, например Заказ_Основание_Контрагент. Это гарантирует, что СКД не «схлопнет» его с другим похожим полем.

Подведем итоги

Проблема «двух точек» в СКД — это не баг, а защитный механизм платформы против неоптимальных запросов. Чтобы обойти это ограничение, мы рекомендуем следующий алгоритм действий:

  1. Первым делом попробуйте применить оператор ВЫРАЗИТЬ — это самый быстрый и «чистый» способ.
  2. Если типов слишком много, используйте Временные Таблицы для явного соединения с нужными данными.
  3. Проверьте настройки Типов значений на закладке «Наборы данных» в СКД.
  4. Избегайте проверок на NULL для полей составного типа, заменяя их типизированными условиями.

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

← На главную