Как добавить дополнительные свойства из регистра «Значения свойств объектов» в сложный запрос 1С?

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия Налоговый учет
← На главную

При разработке отчетов или доработке типовых механизмов программисты 1С часто сталкиваются с необходимостью вывода дополнительных реквизитов (свойств), которые хранятся не в самих документах, а в отдельном регистре сведений ЗначенияСвойствОбъектов. Ситуация осложняется, когда основной запрос уже представляет собой массивную конструкцию из множества блоков ОБЪЕДИНИТЬ ВСЕ. В этой статье мы подробно разберем, как правильно интегрировать данные регистра в сложную структуру запроса, избежав типичных ошибок и падения производительности.

Разбор проблемы: почему возникают сложности

Рассмотрим стандартную ситуацию: у нас есть запрос, который собирает данные по счетам-фактурам, ГТД и другим документам, формируя единую таблицу РеестрСчетовФактур. Автор вопроса столкнулся с тем, что при попытке добавить выборку из регистра сведений напрямую в блоки объединения или при использовании временных таблиц внутри подзапросов, система выдает ошибки типа «Неправильный псевдоним» или «Предложение ПОМЕСТИТЬ может располагаться только в основном запросе».

Выясним причину: основная проблема заключается в попытке «вклиниться» в каждый отдельный блок объединения (для каждого типа документа), что делает код нечитаемым и провоцирует ошибки типизации полей. Правильнее будет работать с результатом объединения как с единым целым.

Решение 1: Левое соединение с результирующей таблицей

Самый эффективный и простой в реализации способ — это выполнить ЛЕВОЕ СОЕДИНЕНИЕ регистра ЗначенияСвойствОбъектов с уже сформированной таблицей (вложенным запросом), которая содержит ссылки на объекты. Проанализируем, как это реализовать структурно.

Рассмотрим пример формирования текста запроса, где мы сначала объединяем все документы, а затем «приклеиваем» к ним значение свойства:


// В начале запроса добавляем поле для будущего значения
Запрос.Текст = 
    "ВЫБРАТЬ РАЗРЕШЕННЫЕ
    |    РеестрСчетовФактур.СчетФактура КАК СчетФактура,
    |    ЗначенияСвойствОбъектов.Значение КАК ДопСвойство,
    |    РеестрСчетовФактур.ДатаРегистрации,
    |    ... (остальные поля)
    |ИЗ
    |    (ВЫБРАТЬ
    |        СчетФактураПолученный.Ссылка КАК СчетФактура,
    |        ...
    |    ИЗ
    |        Документ.СчетФактураПолученный КАК СчетФактураПолученный
    |    
    |    ОБЪЕДИНИТЬ ВСЕ
    |    
    |    ВЫБРАТЬ
    |        ГТДИмпорт.Ссылка,
    |        ...
    |    ИЗ
    |        Документ.ГТДИмпорт КАК ГТДИмпорт
    |    ) КАК РеестрСчетовФактур
    |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов
    |        ПО РеестрСчетовФактур.СчетФактура = ЗначенияСвойствОбъектов.Объект
    |            И (ЗначенияСвойствОбъектов.Свойство = &СвойствоСсылка)";

Обратите внимание на важный момент: условие по конкретному свойству (ЗначенияСвойствОбъектов.Свойство = &СвойствоСсылка) должно находиться именно в секции ПО (условие связи), а не в ГДЕ. Это гарантирует, что если у объекта нет такого свойства, строка не исчезнет из результата, а поле Значение просто останется пустым (NULL).

Решение 2: Использование временных таблиц для оптимизации

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

  1. Создаем первый запрос пакета, который собирает все документы через ОБЪЕДИНИТЬ ВСЕ и сохраняет их в МенеджерВременныхТаблиц с помощью команды ПОМЕСТИТЬ ВТ_Документы.
  2. Во втором запросе пакета выбираем данные из ВТ_Документы и соединяем их с регистром сведений.

Такой подход позволяет избежать ошибки «Предложение ПОМЕСТИТЬ может располагаться только в основном запросе», так как ПОМЕСТИТЬ будет стоять на верхнем уровне первого запроса в пакете.

Оптимизация: Свойство.Код vs Свойство-Параметр

В тексте темы часто встречается фильтрация по коду свойства: ЗначенияСвойствОбъектов.Свойство.Код = "073". Разберем, почему так делать не стоит:

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

2. Надежность: Код свойства может измениться в режиме «1С:Предприятие», и запрос перестанет работать.

Как сделать правильно: Нам следует найти ссылку на свойство заранее в коде и передать её как параметр.


// В модуле перед выполнением запроса
СвойствоОбъекта = ПланыВидовХарактеристик.СвойстваОбъектов.НайтиПоКоду("073");
Запрос.УстановитьПараметр("СвойствоСсылка", СвойствоОбъекта);

Как избежать дублирования строк

При работе с регистром ЗначенияСвойствОбъектов существует риск «размножения» строк. Это происходит, если для одного и того же объекта в регистре по какой-то причине оказалось несколько записей с одинаковым свойством (например, из-за программных ошибок или некорректного переноса данных). Чтобы отчет не выдал удвоенные суммы, проанализируем структуру связи.

Для полной гарантии уникальности можно использовать функцию МАКСИМУМ(ЗначенияСвойствОбъектов.Значение) и сгруппировать результат по всем остальным полям. Однако в большинстве случаев достаточно корректного условия ПО Свойство = &Параметр.

Работа с характеристиками (альтернативный путь для СКД)

Если ваша задача — добавить свойство в отчет, построенный на Системе компоновки данных (СКД), то модифицировать сам текст запроса вообще не обязательно. Рассмотрим, как это сделать через механизм характеристик:

  1. В конструкторе схемы компоновки данных перейдем на закладку «Характеристики».
  2. Добавим новую запись, где укажем тип объекта (например, ДокументСсылка.СчетФактураПолученный).
  3. Укажем, что виды характеристик хранятся в соответствующем плане видов характеристик, а значения — в регистре ЗначенияСвойствОбъектов.
  4. После этого все дополнительные свойства появятся в списке доступных полей отчета автоматически. Система сама добавит нужные соединения в итоговый SQL-запрос, только если пользователь выберет это поле в настройках.

Подведем итог: для добавления данных из ЗначенияСвойствОбъектов в сложный запрос наиболее универсальным является метод ЛЕВОГО СОЕДИНЕНИЯ с результатом вложенного запроса. Важно использовать параметры для ссылок на свойства и следить за тем, чтобы условие фильтрации по конкретному свойству находилось внутри секции связи ПО.

← На главную