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

Программист IT и автоматизация бизнеса
← На главную

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

Поведение пустых коллекций в условиях запроса

Рассмотрим распространенную ошибку: передачу в параметр СписокТоваров пустого массива или пустого объекта СписокЗначений. Если передать в условие В или В ИЕРАРХИИ пустую коллекцию элементов, платформа 1С интерпретирует такое условие как ЛОЖЬ. В результате запрос вернет пустую выборку (0 строк), а не весь справочник.

Способ 1. Передача пустой ссылки в список значений

Простейший способ обойти это ограничение при отборе по иерархии — передать в список значений пустую ссылку нужного справочника. В платформе 1С пустая ссылка является условным корнем всего дерева иерархии. Выясним причину, почему этот метод работает: проверяя условие вхождения элементов в иерархию пустой ссылки, система считает, что все реальные элементы справочника находятся внутри этого корня.

Рассмотрим пример кода на встроенном языке 1С:


СписокТоваров = Новый СписокЗначений;
// Добавляем пустую ссылку справочника Номенклатура
СписокТоваров.Добавить(Справочники.Номенклатура.ПустаяСсылка());

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

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

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

Способ 2. Условие с дополнительным логическим флагом

Если требуется универсальное условие в тексте запроса без динамической сборки кода, можно добавить дополнительный булевый параметр &ВыбратьВсе.

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

  1. В секции ГДЕ проверяем вхождение в список или значение флага.
  2. Если флаг равен Истина, условие выполняется для всех записей.

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

Запрос.УстановитьПараметр("СписокТоваров", СписокТоваров);
Запрос.УстановитьПараметр("ВыбратьВсе", НЕ ЗначениеЗаполнено(СписокТоваров));

Способ 3. Динамическое формирование текста запроса (Рекомендуемый подход)

Наиболее оптимальным решением с точки зрения производительности и стандартов разработки 1С является динамическая сборка текста запроса. Перед выполнением запроса проверяется заполнение переменной с помощью функции ЗначениеЗаполнено(). Если отбор задан — секция ГДЕ добавляется в текст запроса. Если отбор не нужен — секция ГДЕ опускается, и СУБД не тратит ресурсы на лишние проверки.

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


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

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

Запрос = Новый Запрос(ТекстЗапроса);

Если ЗначениеЗаполнено(СписокТоваров) Тогда
    Запрос.УстановитьПараметр("СписокТоваров", СписокТоваров);
КонецЕсли;

РезультатЗапроса = Запрос.Выполнить();

Способ 4. Использование фигурных скобок в СКД и динамических списках

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


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

В этом случае платформа автоматически удалит секцию отбора из итогового SQL-запроса, если параметр не был передан или элемент отбора отключен пользователем.

← На главную