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