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