Как в запросе 1С указать конкретную папку номенклатуры в условии В ИЕРАРХИИ

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

При работе с запросами в системе «1С:Предприятие 8» часто возникает задача отфильтровать элементы справочника (например, номенклатуру) так, чтобы в выборку попали только те объекты, которые находятся внутри определенной папки или ее подпапок. Самым логичным инструментом для этого является оператор В ИЕРАРХИИ. Однако новички часто сталкиваются с вопросом: как именно передать конкретную папку в это условие, если мы не хотим или не можем использовать внешние параметры запроса? Давайте подробно разберем все доступные методы, проанализируем их плюсы и минусы, а также выясним, какой из них считается наиболее профессиональным.

Метод 1. Использование подзапроса для поиска по наименованию

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


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Наименование КАК Наименование
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Ссылка В ИЕРАРХИИ (
        ВЫБРАТЬ ПЕРВЫЕ 1
            Г.Ссылка
        ИЗ
            Справочник.Номенклатура КАК Г
        ГДЕ
            Г.ЭтоГруппа
            И Г.Наименование = "Конфеты"
    )

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

Метод 2. Использование предопределенных элементов (Самый надежный способ)

Разберем ситуацию, когда папка, к которой мы обращаемся, создана разработчиком в конфигураторе. Это идеальный сценарий с точки зрения стабильности системы. К таким элементам в запросе можно обращаться напрямую через конструкцию ЗНАЧЕНИЕ. Это избавляет систему от необходимости искать ссылку по строковому имени и гарантирует, что даже при переименовании папки пользователем код продолжит работать корректно.

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


ВЫБРАТЬ
    Номенклатура.Наименование КАК Наименование
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Ссылка В ИЕРАРХИИ (ЗНАЧЕНИЕ(Справочник.Номенклатура.ПродукцияСобственногоПроизводства))

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

Метод 3. Программная подстановка ссылки через параметры

Если папка создана пользователем в режиме «Предприятие», мы не можем обратиться к ней через ЗНАЧЕНИЕ. В этом случае правильным подходом будет сначала найти ссылку на папку в коде 1С, а затем передать ее в запрос в качестве параметра. Рассмотрим, как это сделать правильно:


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

// Находим группу один раз перед выполнением запроса
ГруппаДляПоиска = Справочники.Номенклатура.НайтиПоНаименованию("Конфеты");

Если ГруппаДляПоиска.Пустая() Тогда
    Сообщить("Группа не найдена!");
Иначе
    Запрос.УстановитьПараметр("Группа", ГруппаДляПоиска);
    Результат = Запрос.Выполнить();
КонецЕсли;

Почему этот метод лучше, чем склейка строки запроса? Во-первых, это предотвращает ошибки кеширования плана запроса в СУБД. Во-вторых, код становится более читаемым и отлаживаемым. Вы всегда можете проверить содержимое переменной ГруппаДляПоиска перед тем, как выполнять тяжелую операцию поиска в иерархии.

Метод 4. Динамическая склейка текста запроса (Не рекомендуется)

Иногда встречается вариант, когда ссылку пытаются «вклеить» прямо в текст запроса. Выглядит это примерно так:


ТекстЗапроса = "ВЫБРАТЬ ... ГДЕ Номенклатура.Ссылка В ИЕРАРХИИ(" + СсылкаНаГруппу + ")";

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

Метод 5. Поиск по уникальному идентификатору (GUID)

Если папка не является предопределенной, но вы точно знаете, какая именно папка вам нужна (и хотите избежать проблем с дублями имен), можно использовать поиск по GUID. Это «золотая середина» между жестким кодом и гибкостью. У каждой ссылки в 1С есть уникальный идентификатор, который не меняется при переименовании папки.

Выясним, как применить этот метод по шагам:

  1. Узнайте GUID нужной папки (например, с помощью консоли запросов или программно через Ссылка.УникальныйИдентификатор()).
  2. В коде создайте ссылку по этому идентификатору.
  3. Передайте ссылку в параметр запроса.

ИдентификаторГруппы = Новый УникальныйИдентификатор("550e8400-e29b-41d4-a716-446655440000");
ГруппаСсылка = Справочники.Номенклатура.ПолучитьСсылку(ИдентификаторГруппы);

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

Проблема производительности иерархических запросов

Важно помнить, что оператор В ИЕРАРХИИ является ресурсоемким. При его использовании СУБД выполняет рекурсивное сканирование таблиц, чтобы найти всех потомков указанного родителя. Проанализируем, как можно оптимизировать такие задачи:

Итоги

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

← На главную