При разработке отчетов и обработок в 1С часто возникает задача: выполнить выборку из иерархического справочника с отбором по выбранным группам или элементам, а в случае, если отбор не задан пользователем — выгрузить весь справочник целиком. Проанализируем ситуацию, когда в запросе используется конструкция В ИЕРАРХИИ, и разберем варианты решения этой задачи.
Рассмотрим распространенную ошибку: передачу в параметр СписокТоваров пустого массива или пустого объекта СписокЗначений. Если передать в условие В или В ИЕРАРХИИ пустую коллекцию элементов, платформа 1С интерпретирует такое условие как ЛОЖЬ. В результате запрос вернет пустую выборку (0 строк), а не весь справочник.
Простейший способ обойти это ограничение при отборе по иерархии — передать в список значений пустую ссылку нужного справочника. В платформе 1С пустая ссылка является условным корнем всего дерева иерархии. Выясним причину, почему этот метод работает: проверяя условие вхождения элементов в иерархию пустой ссылки, система считает, что все реальные элементы справочника находятся внутри этого корня.
Рассмотрим пример кода на встроенном языке 1С:
СписокТоваров = Новый СписокЗначений;
// Добавляем пустую ссылку справочника Номенклатура
СписокТоваров.Добавить(Справочники.Номенклатура.ПустаяСсылка());
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В ИЕРАРХИИ(&СписокТоваров)";
Запрос.УстановитьПараметр("СписокТоваров", СписокТоваров);
РезультатЗапроса = Запрос.Выполнить();
Важное предупреждение по производительности: Использование конструкции В ИЕРАРХИИ с пустой ссылкой для отключения отбора не рекомендуется на больших объемах данных. К СУБД отправляются тяжелые рекурсивные запросы и выполняется полное сканирование таблицы, что может вызывать существенное падение скорости работы системы.
Если требуется универсальное условие в тексте запроса без динамической сборки кода, можно добавить дополнительный булевый параметр &ВыбратьВсе.
Разберем по шагам логику построения такого запроса:
ГДЕ проверяем вхождение в список или значение флага.Истина, условие выполняется для всех записей.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| (Номенклатура.Ссылка В (&СписокТоваров) ИЛИ &ВыбратьВсе)";
Запрос.УстановитьПараметр("СписокТоваров", СписокТоваров);
Запрос.УстановитьПараметр("ВыбратьВсе", НЕ ЗначениеЗаполнено(СписокТоваров));
Наиболее оптимальным решением с точки зрения производительности и стандартов разработки 1С является динамическая сборка текста запроса. Перед выполнением запроса проверяется заполнение переменной с помощью функции ЗначениеЗаполнено(). Если отбор задан — секция ГДЕ добавляется в текст запроса. Если отбор не нужен — секция ГДЕ опускается, и СУБД не тратит ресурсы на лишние проверки.
Рассмотрим пример реализации:
ТекстЗапроса =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
Если ЗначениеЗаполнено(СписокТоваров) Тогда
ТекстЗапроса = ТекстЗапроса + "
|ГДЕ
| Номенклатура.Ссылка В ИЕРАРХИИ(&СписокТоваров)";
КонецЕсли;
Запрос = Новый Запрос(ТекстЗапроса);
Если ЗначениеЗаполнено(СписокТоваров) Тогда
Запрос.УстановитьПараметр("СписокТоваров", СписокТоваров);
КонецЕсли;
РезультатЗапроса = Запрос.Выполнить();
При разработке отчетов на Системе компоновки данных (СКД) или при настройке динамических списков необязательные условия оформляются с помощью расширения языка запросов (фигурных скобок):
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
{ГДЕ
Номенклатура.Ссылка В ИЕРАРХИИ (&СписокТоваров)}
В этом случае платформа автоматически удалит секцию отбора из итогового SQL-запроса, если параметр не был передан или элемент отбора отключен пользователем.