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

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

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

В этой статье мы подробно разберем природу таких реквизитов, выясним, где они хранятся физически, и рассмотрим три практических способа их извлечения для построения отчетов: от простых запросов до профессиональной настройки механизма характеристик в Системе компоновки данных (СКД).

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

---

Понимаем архитектуру: Дополнительные реквизиты vs Дополнительные сведения

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

  1. Дополнительные реквизиты — являются частью самого объекта. Физически они записываются и хранятся в подчиненной табличной части конкретного документа или справочника. Эта табличная часть всегда называется ДополнительныеРеквизиты. В ней содержатся колонки:
    • Свойство — ссылка на план видов характеристик ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения;
    • Значение — значение этого свойства (может быть числом, строкой, датой или ссылкой);
    • ТекстоваяСтрока — используется для хранения длинных текстовых значений.
  2. Дополнительные сведения — хранятся отдельно от самого объекта базы данных. Для их хранения используется независимый регистр сведений РегистрСведений.ДополнительныеСведения. Сведения используются тогда, когда редактирование свойств не должно приводить к изменению самого документа (например, закрытый период) или когда это свойство относится к объекту косвенно.

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

---

Способ 1. Профессиональное решение для СКД через механизм «Характеристики»

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

Давайте выполним настройку по шагам:

  1. Откройте схему компоновки данных (схему СКД) вашего отчета.
  2. Перейдите на самую первую вкладку «Характеристики» (она находится рядом с вкладками «Наборы данных» и «Связи наборов данных»).
  3. Добавьте новую строку в таблицу характеристик и заполните ее следующими параметрами:
    • Тип: Выберите объект метаданных, свойства которого мы хотим получить. В нашем случае это ДокументСсылка.ЗаказКлиента.
    • Источник видов: Установите значение Таблица.
    • Виды характеристик: Укажите таблицу метаданных, где хранятся сами настройки свойств. Для БСП это ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения.
    • Поле ключа: Выберите поле Ссылка.
    • Поле имени: Выберите поле Наименование.
    • Поле типа значения: Выберите поле ТипЗначения.
    • Источник значений: Установите значение Таблица.
    • Значения характеристик: Укажите подчиненную табличную часть документа, где хранятся значения. Для нашего примера это Документ.ЗаказКлиента.ДополнительныеРеквизиты.
    • Поле объекта: Укажите Ссылка (это поле связывает табличную часть с самим документом).
    • Поле вида: Укажите Свойство.
    • Поле значения: Укажите Значение.

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

---

Способ 2. Извлечение дополнительных реквизитов в запросе (Левое соединение)

Рассмотрим ситуацию, когда отчет строится не на СКД, а данные нужно получить непосредственно в коде модуля с помощью обычного запроса. Начинающие программисты часто совершают ошибку, делая простое соединение с табличной частью. Это приводит к дублированию строк в результате запроса (так называемому «декартову произведению»), если у документа заполнено несколько дополнительных реквизитов.

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


ВЫБРАТЬ
    Реализация.Ссылка КАК РеализацияСсылка,
    Реализация.Дата КАК ДатаРеализации,
    Реализация.Номер КАК НомерРеализации,
    Реализация.ЗаказКлиента КАК ЗаказКлиента,
    
    // Получаем значения из соединенных табличных частей
    ЕСТЬNULL(ДопРеквизитНомер.Значение, "") КАК НомерЗаказаССайта,
    ЕСТЬNULL(ДопРеквизитДата.Значение, ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаЗаказаССайта
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
    
    // Соединяемся с документом ЗаказКлиента для доступа к его ТЧ
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК ЗаказКлиентаОбъект
        ПО Реализация.ЗаказКлиента = ЗаказКлиентаОбъект.Ссылка
        
    // Первое левое соединение для получения Номера заказа с сайта
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ДопРеквизитНомер
        ПО Реализация.ЗаказКлиента = ДопРеквизитНомер.Ссылка
        И ДопРеквизитНомер.Свойство = &СвойствоНомерЗаказа
        
    // Второе левое соединение для получения Даты заказа с сайта
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ДопРеквизитДата
        ПО Реализация.ЗаказКлиента = ДопРеквизитДата.Ссылка
        И ДопРеквизитДата.Свойство = &СвойствоДатаЗаказа
ГДЕ
    Реализация.Проведен = ИСТИНА

Важное примечание по передаче параметров: В параметры &СвойствоНомерЗаказа и &СвойствоДатаЗаказа необходимо передать конкретные элементы плана видов характеристик. В коде это можно сделать следующим образом:


Запрос.УстановитьПараметр("СвойствоНомерЗаказа", 
    ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Номер заказа с сайта (Заказ клиента)"));

Запрос.УстановитьПараметр("СвойствоДатаЗаказа", 
    ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Дата заказа с сайта (Заказ клиента)"));

Использование метода НайтиПоНаименованию допустимо, однако наименование должно в точности совпадать с тем, как реквизит записан в справочнике вашей информационной базы.

---

Способ 3. Оптимизированный запрос с использованием Временных Таблиц (для больших баз)

Если в вашей информационной базе хранятся сотни тысяч документов «Заказ клиента» и «Реализация товаров и услуг», прямое левое соединение с табличными частями документов "в лоб" может привести к существенному замедлению работы СУБД. В этом случае мы рекомендуем использовать временные таблицы для предварительного отбора данных.

Давайте проанализируем оптимизированный вариант построения запроса:


// Шаг 1: Выбираем только нужные документы Реализации за период во временную таблицу
ВЫБРАТЬ
    Реализация.Ссылка КАК Ссылка,
    Реализация.ЗаказКлиента КАК ЗаказКлиента
ПОМЕСТИТЬ ВТ_Реализации
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    Реализация.Проведен = ИСТИНА
    И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
ИНДЕКСИРОВАТЬ ПО
    ЗаказКлиента
;

////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Выбираем дополнительные реквизиты только для отобранных Заказов
ВЫБРАТЬ
    ТЧ_ДопРеквизиты.Ссылка КАК Ссылка,
    МАКСИМУМ(ВЫБОР
            КОГДА ТЧ_ДопРеквизиты.Свойство = &СвойствоНомерЗаказа
                ТОГДА ТЧ_ДопРеквизиты.Значение
            ИНАЧЕ НЕОПРЕДЕЛЕНО
        КОНЕЦ) КАК НомерЗаказаССайта,
    МАКСИМУМ(ВЫБОР
            КОГДА ТЧ_ДопРеквизиты.Свойство = &СвойствоДатаЗаказа
                ТОГДА ТЧ_ДопРеквизиты.Значение
            ИНАЧЕ НЕОПРЕДЕЛЕНО
        КОНЕЦ) КАК ДатаЗаказаССайта
ПОМЕСТИТЬ ВТ_ДопСвойстваЗаказов
ИЗ
    Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ТЧ_ДопРеквизиты
ГДЕ
    ТЧ_ДопРеквизиты.Ссылка В
            (ВЫБРАТЬ РАЗЛИЧНЫЕ
                ВТ_Реализации.ЗаказКлиента
            ИЗ
                ВТ_Реализации)
    И ТЧ_ДопРеквизиты.Свойство В (&СписокСвойств)
ГРУППИРОВАТЬ ПО
    ТЧ_ДопРеквизиты.Ссылка
ИНДЕКСИРОВАТЬ ПО
    Ссылка
;

////////////////////////////////////////////////////////////////////////////////
// Шаг 3: Соединяем подготовленные таблицы для получения финального результата
ВЫБРАТЬ
    Реализации.Ссылка КАК РеализацияСсылка,
    Реализации.ЗаказКлиента КАК ЗаказКлиента,
    ЕСТЬNULL(ДопСвойства.НомерЗаказаССайта, "") КАК НомерЗаказаССайта,
    ЕСТЬNULL(ДопСвойства.ДатаЗаказаССайта, ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаЗаказаССайта
ИЗ
    ВТ_Реализации КАК Реализации
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДопСвойстваЗаказов КАК ДопСвойства
        ПО Реализации.ЗаказКлиента = ДопСвойства.Ссылка

Почему этот подход работает быстрее?

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

← На главную