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