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

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

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

Постановка задачи и типичная ошибка начинающих

Представим, что у нас есть документ движения запасов, и мы хотим получить остатки или обороты в разрезе номенклатуры, характеристик, а также дополнительно вытащить штрихкод, цвет и размер. Характеристики хранятся в справочнике ХарактеристикиНоменклатуры, а их значения (цвет, размер) — в табличной части ДополнительныеРеквизиты этого же справочника.

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


ВЫБРАТЬ
    ВТ_Запасы.Номенклатура КАК Номенклатура,
    ВТ_Запасы.Характеристика КАК Характеристика,
    ВТ_Запасы.Количество КАК Количество,
    ХарактеристикиНоменклатуры.ДополнительныеРеквизиты.Значение КАК Значение
ИЗ
    ВТ_Запасы КАК ВТ_Запасы
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК ХарактеристикиНоменклатуры
        ПО ВТ_Запасы.Характеристика = ХарактеристикиНоменклатуры.Ссылка
ГДЕ
    (ХарактеристикиНоменклатуры.ДополнительныеРеквизиты.Свойство = &Цвет
        ИЛИ ХарактеристикиНоменклатуры.ДополнительныеРеквизиты.Свойство = &Размер)

В чем здесь проблема? Конструкция отрабатывает, но если в документе встречается позиция с пустой характеристикой (или характеристикой без нужных свойств), то такая строка полностью пропадает из результатов запроса! Это происходит потому, что наложение условия в секции ГДЕ на присоединенную таблицу фактически превращает ЛЕВОЕ СОЕДИНЕНИЕ во внутреннее. Выясним причину: если записи в правой таблице нет, поле свойства принимает значение NULL, условие в секции ГДЕ не выполняется, и строка отсекается.

Решение 1: Правильное использование ЛЕВОГО СОЕДИНЕНИЯ

Чтобы избежать отсечения строк с пустыми характеристиками, перенесем условия фильтрации прямо в условие соединения (в секцию ПО). Кроме того, для получения значений в разные колонки нам потребуется присоединить табличную часть ДополнительныеРеквизиты столько раз, сколько свойств мы хотим получить (один раз для цвета, второй раз для размера).

Рассмотрим исправленный и рабочий вариант запроса:


ВЫБРАТЬ
    ВТ_Запасы.Номенклатура КАК Номенклатура,
    ВТ_Запасы.Характеристика КАК Характеристика,
    ВТ_Запасы.Количество КАК Количество,
    ХарактеристикиЦвет.Значение КАК Цвет,
    ХарактеристикиРазмер.Значение КАК Размер
ИЗ
    ВТ_Запасы КАК ВТ_Запасы
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры.ДополнительныеРеквизиты КАК ХарактеристикиЦвет
        ПО ВТ_Запасы.Характеристика = ХарактеристикиЦвет.Ссылка
            И (ХарактеристикиЦвет.Свойство = &Цвет)
            
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры.ДополнительныеРеквизиты КАК ХарактеристикиРазмер
        ПО ВТ_Запасы.Характеристика = ХарактеристикиРазмер.Ссылка
            И (ХарактеристикиРазмер.Свойство = &Размер)

Обратите внимание: мы напрямую обращаемся к табличной части Справочник.ХарактеристикиНоменклатуры.ДополнительныеРеквизиты и даем ей разные псевдонимы (ХарактеристикиЦвет и ХарактеристикиРазмер). Теперь, даже если цвет или размер не заполнены, основная запись из ВТ_Запасы никуда не исчезнет, а в колонках свойств просто появится NULL.

Решение 2: Разворот строк в колонки через ВЫБОР КОГДА (Свертка)

Если свойств много, плодить десятки левых соединений может быть накладно для производительности базы данных. Существует альтернативный классический паттерн преобразования строк дополнительных реквизитов в колонки. В SQL он обычно реализуется функциями PIVOT, но в 1С мы используем комбинацию агрегатной функции МАКСИМУМ и конструкции ВЫБОР КОГДА.

Проанализируем этот подход. Суть в том, чтобы сделать всего одно левое соединение с таблицей свойств, а затем сгруппировать результат, выделяя нужные свойства через условия:


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

В этом случае база данных прочитает таблицу свойств лишь один раз. Затем механизм группировки платформы 1С "схлопнет" записи по номенклатуре и характеристике. Функция МАКСИМУМ выберет непустое значение для цвета и размера из множества объединенных строк. Это более профессиональный и часто более быстрый способ для большого числа характеристик.

Альтернативные подходы: СКД и БСП

Если вы пишете запрос не для обработки данных в коде, а для вывода отчета пользователю, то зачастую собирать свойства левыми соединениями вообще не нужно. Платформа 1С предоставляет мощные стандартные инструменты.

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

Подводя итоги, мы рассмотрели несколько путей решения задачи. Выбор метода зависит от контекста: для небольшого числа фиксированных свойств отлично подойдут левые соединения, для динамического набора реквизитов в коде — свертка через ВЫБОР КОГДА или функции БСП, а для отчетов абсолютным лидером по удобству остается механизм характеристик СКД. Используйте эти подходы в своей разработке, и ваши запросы всегда будут работать корректно и быстро!

← На главную