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

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

При работе с типовыми конфигурациями 1С, такими как ERP, Управление торговлей или Комплексная автоматизация, программисты часто сталкиваются с необходимостью отобрать объекты (например, номенклатуру) по нескольким дополнительным реквизитам. Дополнительные реквизиты хранятся в табличной части ДополнительныеРеквизиты, и попытка написать простое условие ГДЕ с оператором И для разных свойств приводит к тому, что запрос возвращает пустой результат. Это происходит потому, что одна строка табличной части не может содержать одновременно два разных свойства.

В этой статье мы рассмотрим несколько эффективных способов решения этой задачи: от использования классических соединений до работы с механизмами компоновки данных.

Причина ошибки в простом запросе

Разберем типичную ситуацию. Нам нужно найти номенклатуру, у которой «Цвет» — «Красный» И «Размер» — «44». Если мы напишем запрос следующим образом:


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

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

Способ 1: Использование внутренних соединений (Inner Join)

Это самый наглядный и часто используемый метод. Мы выбираем ссылку из справочника и последовательно присоединяем к ней таблицу дополнительных реквизитов столько раз, сколько условий нам нужно проверить. Каждое новое ВНУТРЕННЕЕ СОЕДИНЕНИЕ отсекает те объекты, у которых нет соответствующего реквизита.

Рассмотрим пример кода для двух свойств:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка
ИЗ
    Справочник.Номенклатура КАК Номенклатура
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты1
        ПО Номенклатура.Ссылка = ДопРеквизиты1.Ссылка
        И ДопРеквизиты1.Свойство = &Свойство1
        И ДопРеквизиты1.Значение = &Значение1
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты2
        ПО Номенклатура.Ссылка = ДопРеквизиты2.Ссылка
        И ДопРеквизиты2.Свойство = &Свойство2
        И ДопРеквизиты2.Значение = &Значение2

Проанализируем этот подход: он работает быстро на небольшом количестве свойств, но если условий станет 6 или 10, запрос станет громоздким, а нагрузка на СУБД возрастет из-за большого количества соединений.

Способ 2: Группировка и подсчет количества (Having)

Этот метод считается более «элегантным» и часто более производительным. Мы выбираем все строки, которые соответствуют любому из наших условий (через ИЛИ), а затем группируем результат по ссылке и оставляем только те объекты, у которых количество найденных строк равно количеству наших условий.

Рассмотрим реализацию этого метода:


ВЫБРАТЬ
    ДопРеквизиты.Ссылка КАК Ссылка
ИЗ
    Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты
ГДЕ
    (ДопРеквизиты.Свойство = &Свойство1 И ДопРеквизиты.Значение = &Значение1)
    ИЛИ (ДопРеквизиты.Свойство = &Свойство2 И ДопРеквизиты.Значение = &Значение2)
    ИЛИ (ДопРеквизиты.Свойство = &Свойство3 И ДопРеквизиты.Значение = &Значение3)
СГРУППИРОВАТЬ ПО
    ДопРеквизиты.Ссылка
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ДопРеквизиты.Свойство) = 3

Важный момент: в условии ИМЕЮЩИЕ мы проверяем, что нашлось именно 3 разных свойства. Если в конфигурации допущена ошибка и у одного объекта дважды указано одно и то же свойство с одинаковым значением, оператор РАЗЛИЧНЫЕ внутри КОЛИЧЕСТВО поможет избежать ложноположительных срабатываний.

Способ 3: Использование временных таблиц

Если логика отбора сложная (например, часть свойств должна проверяться на равенство, а часть — на вхождение в список), удобно использовать временные таблицы (МенеджерВременныхТаблиц). Мы можем отобрать подходящие ссылки по первому свойству во временную таблицу ВТ_Свойство1, затем из нее отобрать данные по второму свойству в ВТ_Свойство2 и так далее.

Пример построения цепочки фильтров:


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

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

Способ 4: Механизм характеристик в СКД

Для создания отчетов наиболее правильным решением будет использование механизма Характеристик в Системе компоновки данных (СКД). Это позволяет пользователю выбирать дополнительные реквизиты прямо в дереве полей, как если бы они были обычными реквизитами объекта.

Выполним следующие шаги для настройки:

  1. Откроем схему компоновки данных.
  2. Перейдем на закладку Характеристики.
  3. Добавим новую запись:
    • Тип объекта: СправочникСсылка.Номенклатура
    • Источник видов характеристик: План видов характеристик ДополнительныеРеквизитыИСведения
    • Источник значений: Табличная часть ДополнительныеРеквизиты

После этой настройки в консоли отчетов или в конструкторе запроса мы сможем обращаться к полям через точку, например: Номенклатура.[Цвет]. Платформа самостоятельно сформирует оптимальный SQL-запрос с левыми соединениями для каждого выбранного поля.

Оптимизация и производительность

При работе с большими базами данных (десятки тысяч позиций номенклатуры) следует учитывать несколько нюансов:

Подводя итог, можно сказать, что выбор метода зависит от контекста. Для быстрого разового запроса в коде отлично подойдет Способ 2 (с группировкой), а для сложных пользовательских отчетов в интерфейсе — Способ 4 (характеристики СКД). Мы проанализировали основные подходы и теперь можем эффективно комбинировать их для решения любых задач автоматизации на платформе 1С.

← На главную