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