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