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

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

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

В этой статье мы подробно разберем, как правильно построить запрос, чтобы найти характеристику, у которой установлены два и более конкретных дополнительных реквизита. Мы проанализируем различные подходы — от временных таблиц до использования агрегатных функций.

Почему стандартный запрос не находит данные?

Рассмотрим ситуацию: нам нужно найти характеристику, у которой «Разрешение» равно «1920x1080» И «Тип матрицы» равен «IPS». Если мы напишем простой запрос к табличной части ДополнительныеРеквизиты с условием ГДЕ (Свойство = &Свойство1 И Значение = &Значение1) И (Свойство = &Свойство2 И Значение = &Значение2), система вернет пустой результат. Это происходит потому, что СУБД проверяет каждую строку отдельно, а в одной строке не может быть сразу два разных свойства.

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

Способ 1. Использование временных таблиц (Метод пересечения)

Этот метод наиболее нагляден и часто используется начинающими разработчиками для понимания логики процесса. Мы последовательно выбираем ссылки во временные таблицы и соединяем их.

Разберем по шагам выполнение такого запроса:

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

Проанализируем пример кода:


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

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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_ПервоеСвойство.Ссылка КАК Ссылка
ИЗ
    ВТ_ПервоеСвойство КАК ВТ_ПервоеСвойство
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ВтороеСвойство КАК ВТ_ВтороеСвойство
        ПО ВТ_ПервоеСвойство.Ссылка = ВТ_ВтороеСвойство.Ссылка

Преимущество: Логика запроса абсолютно прозрачна. Легко отлаживать каждую временную таблицу по отдельности в консоли запросов.

Способ 2. Множественное соединение одной таблицы

Если параметров поиска немного (например, строго два или три), мы можем обойтись без временных таблиц, используя псевдонимы для одной и той же таблицы дополнительных реквизитов. Рассмотрим, как это реализовать.

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


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

В данном примере ДопРеквизиты1 и ДопРеквизиты2 — это физически одна и та же таблица, но обращение к ним идет как к разным сущностям. Если у характеристики есть обе строки, она попадет в результат.

Способ 3. Группировка и условие ИМЕЮЩИЕ (HAVING)

Этот метод считается наиболее профессиональным и гибким, особенно если количество фильтров может меняться (например, пользователь сам выбирает, по скольким свойствам искать). Посмотрим на алгоритм:

  1. Выбираем все строки из таблицы доп. реквизитов, которые соответствуют любому из наших условий (используем оператор ИЛИ или В списке).
  2. Группируем результат по ссылке на характеристику.
  3. Считаем количество найденных различных свойств для каждой ссылки.
  4. Если количество совпадений равно количеству искомых параметров, значит, характеристика нам подходит.

Посмотрим на пример реализации:


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

Важный нюанс: В условии ИМЕЮЩИЕ мы указываем число 2, так как ищем два свойства. Если вы программно формируете запрос для 5 свойств, просто подставьте нужное число в параметр.

Оптимизация: отказ от поиска по наименованию

Разберем распространенную ошибку, которая встречалась в сообщениях форума. Автор пытался искать свойства и значения по их строковому представлению: ДополнительныеРеквизиты.Значение.Наименование = &ЗначениеНаименование.

Проанализируем, почему это плохо:

Правильный подход: Сначала в коде 1С (на языке 1С) найдите ссылки на нужные свойства и значения, а затем передайте их в запрос как параметры. Например:


СвойствоСсылка = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Разрешение");
ЗначениеСсылка = Справочники.ЗначенияСвойствОбъектов.НайтиПоНаименованию("1920x1080", , СвойствоСсылка);

Запрос.УстановитьПараметр("Свойство1", СвойствоСсылка);
Запрос.УстановитьПараметр("Значение1", ЗначениеСсылка);

Особенности работы с владельцем характеристики

Выясним еще одну важную деталь. Характеристики в 1С могут принадлежать либо конкретной Номенклатуре, либо Виду номенклатуры (общие характеристики). Если в вашем запросе жестко прописано условие Владелец = &Номенклатура, вы рискуете не найти общие характеристики, которые также могут использоваться для данного товара.

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

Резюме

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

← На главную