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