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