При работе с современными конфигурациями 1С, такими как Управление торговлей 11, ERP или Комплексная автоматизация, мы часто сталкиваемся с необходимостью подбора товаров по техническим характеристикам. Эти характеристики обычно хранятся в табличной части ДополнительныеРеквизиты. Основная сложность заключается в том, что стандартный запрос с использованием оператора В в условии ГДЕ работает по логике «ИЛИ». Если мы укажем в параметрах «DDR4» и «16 Гб», система выдаст нам всю номенклатуру, где есть либо DDR4, либо 16 Гб. Наша же задача — найти только те позиции, где присутствуют оба этих свойства одновременно.
Разберем детально, как реализовать логику «И» для произвольного количества свойств и значений, чтобы обеспечить точный поиск номенклатуры.
Проанализируем наиболее эффективный и масштабируемый способ решения задачи. Этот метод основан на группировке записей по ссылке на номенклатуру и последующей фильтрации тех групп, в которых количество найденных уникальных свойств совпадает с количеством заданных критериев поиска.
Рассмотрим логику работы этого запроса. Допустим, нам нужно найти оперативную память с тремя параметрами: частота 2133 МГц, объем 16 Гб и тип DDR4. Если мы просто выберем все строки табличной части, подходящие под эти условия, то для одной номенклатуры может найтись от 1 до 3 строк. Нам нужны только те, для которых нашлось ровно 3 строки.
Посмотрим на пример реализации такого запроса:
ВЫБРАТЬ
НоменклатураДополнительныеРеквизиты.Ссылка КАК Номенклатура
ИЗ
Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДополнительныеРеквизиты
ГДЕ
(НоменклатураДополнительныеРеквизиты.Свойство = &Свойство1 И НоменклатураДополнительныеРеквизиты.Значение = &Значение1)
ИЛИ (НоменклатураДополнительныеРеквизиты.Свойство = &Свойство2 И НоменклатураДополнительныеРеквизиты.Значение = &Значение2)
ИЛИ (НоменклатураДополнительныеРеквизиты.Свойство = &Свойство3 И НоменклатураДополнительныеРеквизиты.Значение = &Значение3)
ГРУППИРОВАТЬ ПО
НоменклатураДополнительныеРеквизиты.Ссылка
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ НоменклатураДополнительныеРеквизиты.Свойство) = &КоличествоКритериев
В данном случае параметр &КоличествоКритериев будет равен 3. Выясним, почему этот метод считается оптимальным:
ГДЕ и значение итогового счетчика.КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) страхует от ошибок, если вдруг в базе данных по какой-то причине задублированы значения свойств для одной номенклатуры.Рассмотрим альтернативный подход, который часто встречается в старых школах разработки. Суть заключается в том, чтобы для каждого искомого свойства присоединять таблицу дополнительных реквизитов заново через ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Поскольку соединение внутреннее, в итоговую выборку попадут только те ссылки, которые есть во всех соединяемых наборах данных.
Проанализируем пример динамического текста запроса:
ВЫБРАТЬ
СпрНоменклатура.Ссылка КАК Номенклатура
ИЗ
Справочник.Номенклатура КАК СпрНоменклатура
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК Свойство1
ПО СпрНоменклатура.Ссылка = Свойство1.Ссылка
И Свойство1.Свойство = &Свойство1
И Свойство1.Значение = &Значение1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК Свойство2
ПО СпрНоменклатура.Ссылка = Свойство2.Ссылка
И Свойство2.Свойство = &Свойство2
И Свойство2.Значение = &Значение2
Важный нюанс: Этот метод хорошо работает, когда свойств немного (2-3). Однако при увеличении количества условий до 10 и более, количество соединений в запросе может негативно сказаться на скорости выполнения, так как планировщику SQL-запросов будет сложнее построить оптимальный план выполнения.
Выясним важную техническую деталь, упомянутую в обсуждении. Поле Значение в табличной части ДополнительныеРеквизиты имеет составной тип. Это означает, что там могут храниться как ссылки (на справочник ЗначенияСвойствОбъектов), так и числа, строки или даты.
При формировании массива параметров или динамического условия ГДЕ, крайне важно соблюдать типизацию:
16, а не строку "16".ЗначенияСвойствОбъектов (например, ссылку на элемент с наименованием "DDR4").Если типы данных в вашем фильтре не будут совпадать с типами, указанными в Плане видов характеристик для данных свойств, запрос просто вернет пустой результат, даже если визуально значения кажутся одинаковыми.
Если задача требует сложной логики (например, пересечение свойств с учетом остатков на складах), можно применить метод последовательного уточнения выборки через временные таблицы.
Разберем этот процесс по шагам:
ВТ_Фильтр, куда помещаем все ссылки номенклатуры, обладающие первым свойством.ВТ_Фильтр, соединяем их с таблицей доп. реквизитов и оставляем только те, у которых есть второе свойство. Результат помещаем в новую временную таблицу (или заменяем старую).Этот способ менее производителен, чем первый, но он бывает полезен при отладке сложных алгоритмов подбора, когда нужно видеть промежуточный результат на каждом этапе фильтрации.
Для создания универсального механизма поиска рекомендуем программно формировать текст запроса. В качестве входящего параметра лучше всего использовать ТаблицаЗначений или Массив Структур, где каждая структура содержит поля Свойство и Значение.
Проанализируем примерный алгоритм подготовки запроса на языке 1С:
ТекстУсловий = "";
Количество = СписокПараметров.Количество();
Для Сч = 1 По Количество Цикл
ТекстУсловий = ТекстУсловий + " (Свойство = &Свойство" + Сч + " И Значение = &Значение" + Сч + ")";
Если Сч <> Количество Тогда
ТекстУсловий = ТекстУсловий + " ИЛИ ";
КонецЕсли;
Запрос.УстановитьПараметр("Свойство" + Сч, СписокПараметров[Сч-1].Свойство);
Запрос.УстановитьПараметр("Значение" + Сч, СписокПараметров[Сч-1].Значение);
КонецЦикла;
Запрос.Текст =
"ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура.ДополнительныеРеквизиты
|ГДЕ " + ТекстУсловий + "
|ГРУППИРОВАТЬ ПО Ссылка
|ИМЕЮЩИЕ КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Свойство) = &Количество";
Запрос.УстановитьПараметр("Количество", Количество);
Используя данный подход, вы получите максимально гибкий и быстрый инструмент для реализации поиска «как в интернет-магазине», где пользователь может выбрать любое количество фильтров, и система мгновенно найдет подходящие товары, строго соответствующие всем заданным критериям.