Как в запросе 1С выбрать объекты, имеющие одновременно несколько заданных значений в одной табличной части?

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

При разработке на платформе 1С:Предприятие программисты часто сталкиваются с задачей фильтрации элементов справочника или документов по данным их табличных частей. Типичный пример: нужно найти объект, у которого в табличной части Параметры есть одновременно и «Цвет = Красный», и «Размер = Большой». Обычное условие ГДЕ в данном случае не сработает напрямую, так как одна строка табличной части не может содержать сразу два разных значения одного реквизита. В этой статье мы подробно разберем, как правильно составить такой запрос, проанализируем различные подходы и выберем наиболее оптимальные с точки зрения производительности.

Метод 1. Использование группировки и условия ИМЕЮЩИЕ (Реляционное деление)

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

Предположим, нам нужно найти объекты, у которых в ТЧ Параметры есть два конкретных значения. Мы можем использовать следующий код:


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

Проанализируем ситуацию: почему мы используем КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ТЧ.Параметр)? Это необходимо для защиты от дублей в данных. Если в табличной части объекта по ошибке будут две одинаковые строки, удовлетворяющие одному условию, обычная функция КОЛИЧЕСТВО(*) вернет неверный результат. Использование РАЗЛИЧНЫЕ гарантирует, что мы считаем именно уникальные характеристики.

Этот метод удобен тем, что он легко масштабируется. Если количество параметров изменится (станет 3, 5 или 10), нам достаточно будет расширить условие ГДЕ и передать новое число в параметр &КоличествоПараметров.

Метод 2. Последовательные внутренние соединения (Self-Join)

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

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


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

Выясним причину, по которой этот метод считается одним из самых быстрых. Оптимизаторы СУБД (таких как MS SQL Server или PostgreSQL) очень эффективно обрабатывают INNER JOIN по индексированным полям. В отличие от группировки, здесь системе не нужно сканировать все подходящие строки и потом их пересчитывать — соединение отсекает ненужные записи на раннем этапе выполнения запроса.

Метод 3. Использование вложенных запросов и оператора В

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


ВЫБРАТЬ
    Объекты.Ссылка
ИЗ
    Справочник.Объекты КАК Объекты
ГДЕ
    Объекты.Ссылка В (ВЫБРАТЬ Ссылка ИЗ Справочник.Объекты.Параметры ГДЕ Параметр = &Параметр1 И Значение = &Значение1)
    И Объекты.Ссылка В (ВЫБРАТЬ Ссылка ИЗ Справочник.Объекты.Параметры ГДЕ Параметр = &Параметр2 И Значение = &Значение2)

Проанализируем производительность данного решения. При использовании конструкции В (ВЫБРАТЬ...) на больших объемах данных (сотни тысяч строк) запрос может начать работать крайне медленно. СУБД может выполнять вложенный запрос для каждой строки основной таблицы. Важный момент: если вы решили использовать этот метод, рекомендуется сначала выгрузить результаты подзапросов во временные таблицы и проиндексировать их по полю Ссылка.

Метод 4. Сравнение групп полей (Кортежи) в 1С 8.3

В современных версиях платформы 1С (начиная с 8.3) появилась возможность сравнивать группы полей. Это делает код более лаконичным, особенно если искомые пары «Параметр-Значение» предварительно помещены во временную таблицу.

Рассмотрим пошагово:

  1. Создаем временную таблицу ВТ_Критерии с колонками Параметр и Значение.
  2. Используем конструкцию сравнения групп.

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

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

Оптимизация и важные настройки метаданных

Независимо от выбранного метода, запрос может работать медленно, если не соблюдены правила индексации. Разберем основные требования к метаданным:

  1. Индексирование реквизитов: В табличной части Параметры для реквизитов Параметр и Значение обязательно должно быть установлено свойство «Индексировать» (или «Индексировать с дополнительным упорядочиванием»). Без этого СУБД будет вынуждена делать полный перебор всех строк всех табличных частей (Full Scan).
  2. Временные таблицы: Если искомых объектов очень много, всегда старайтесь работать через МенеджерВременныхТаблиц. Результат поиска ссылок лучше поместить во временную таблицу, проиндексировать её и только потом соединять с основной таблицей справочника для получения детальных данных (наименования, кодов и т.д.).
  3. Механизм характеристик: Если данная задача решается в рамках отчета, посмотрим в сторону СКД (Системы компоновки данных). В настройках набора данных можно описать ТЧ как источник характеристик. Это позволит пользователю в пользовательском режиме просто добавлять отборы, а система сама сформирует оптимальные соединения.

Ограничение: Поиск по точному совпадению набора

Важно различать две задачи: Первая — найти объекты, у которых ЕСТЬ эти два параметра (и, возможно, какие-то другие). Вторая — найти объекты, у которых есть ТОЛЬКО эти два параметра и больше ничего.

Если нам нужно строгое соответствие (только эти параметры), мы должны дополнить условие ИМЕЮЩИЕ. Проанализируем пример:


ИМЕЮЩИЕ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ТЧ.Параметр) = &КоличествоПараметров
    И КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ТЧ.Параметр) = (ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ Справочник.Объекты.Параметры КАК ТЧ_Все ГДЕ ТЧ_Все.Ссылка = ТЧ.Ссылка)

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

Подводя итог, можно сказать, что наиболее универсальным и рекомендуемым к применению является Метод 1 (Группировка и ИМЕЮЩИЕ), так как он обеспечивает отличный баланс между производительностью, читаемостью кода и простотой масштабирования под любое количество параметров.

← На главную