При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда итоговые значения по полю Остаток начинают некорректно увеличиваться (удваиваться, утраиваться и т.д.). Рассмотрим классический пример: в отчете выводятся данные о количестве товара и его ценах в разрезе разных видов цен. Если для одной номенклатуры в базе задано три вида цен, то при обычном соединении таблиц строка с остатком повторится трижды. В результате стандартный ресурс Сумма(Остаток) выдаст результат, умноженный на три. Разберем по шагам, почему это происходит и какими способами можно добиться корректного отображения итогов.
Проанализируем ситуацию с точки зрения теории баз данных. Когда мы объединяем таблицу остатков с таблицей цен в одном запросе, система выполняет левое или внутреннее соединение. Если на одну запись из таблицы остатков (например, Товар №1 — 83 шт.) приходится несколько записей из таблицы цен (Оптовая, Розничная, Закупочная), в итоговой выборке запроса мы получим три строки. В каждой из этих строк будет значиться число 83. Для системы компоновки данных, если не заданы специальные настройки, это три разных числа, которые она добросовестно складывает в итогах, получая 249 вместо 83.
Одним из самых надежных и архитектурно правильных методов является разделение запроса на два независимых набора данных. Рассмотрим, как это реализовать:
Номенклатура (и, если требуется, по характеристикам или складам).При такой структуре СКД сначала получает уникальные записи об остатках, а затем «подтягивает» к ним соответствующие цены. Ресурс Остаток, рассчитанный по первому набору, не будет дублироваться, так как физически в первом наборе данных для каждой номенклатуры существует только одна запись. Это исключает математические ошибки в итогах без написания сложных формул.
Если мы предпочитаем использовать один запрос, нам необходимо «объяснить» системе компоновки, что поле Остаток является особенным. Выясним, как это сделать через механизм ролей:
Остаток.КонечныйОстаток).Правильная настройка ролей позволяет СКД автоматически определять, что при расчете итогов по группировке «Товар» нужно брать значение остатка только один раз, даже если в детальных записях строк стало больше из-за цен. Система будет использовать интеллектуальные алгоритмы агрегации, встроенные в платформу 1С.
Иногда требуется более тонкая настройка итогов, которую невозможно решить только ролями. В этом случае мы можем изменить формулу на вкладке Ресурсы. Вместо стандартного Сумма(Остаток) мы можем использовать функции, которые учитывают группировки.
Рассмотрим пример использования функции Максимум или Среднее. Если в рамках одной номенклатуры остаток всегда одинаков во всех строках (различаются только цены), то формула Максимум(Остаток) в итогах по номенклатуре даст верное число (83). Однако для общих итогов по всему отчету просто Максимум не подойдет, так как он выберет максимальный остаток среди всех товаров.
Для корректного расчета общих итогов по всем товарам используем более сложную конструкцию:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(Остаток)", "Номенклатура"))
Разберем, что делает эта формула:
Максимум(Остаток) — выбирает одно значение остатка для каждой конкретной номенклатуры.ВычислитьВыражениеСГруппировкойМассив — собирает эти значения в массив в контексте группировки по номенклатуре.Сумма(...) — складывает уникальные значения из полученного массива для вывода в итоговую строку.Проанализируем ситуацию, когда нам нужно вывести остаток в отдельной колонке, а цены — в других. Чтобы визуально отделить ресурсы и избежать каши в настройках, можно воспользоваться советом опытных разработчиков: создать вычисляемое поле, которое будет служить «контейнером».
ЗаголовокЦен с выражением "Цены номенклатуры".Цена.Остаток и Стоимость оставим в основных колонках или в другой группе.Такой подход позволяет визуально структурировать отчет. Помните, что если вы добавляете поля в Выбранные поля конкретной группировки, они будут выводиться именно там. Если вы хотите видеть остаток только в итоговой строке или в начале строки, не добавляйте его в группировку, где происходит размножение данных по видам цен.
Для решения проблемы с «двоением» остатков в СКД рекомендуем придерживаться следующего алгоритма:
Во-первых, проверьте настройки ролей полей. Это самый быстрый способ, предусмотренный платформой.
Во-вторых, если роли не помогают или отчет сложный, разделите получение остатков и получение цен на два разных набора данных (запроса), связав их по ключевым полям.
В-третьих, используйте продвинутые агрегатные функции в ресурсах, такие как ВычислитьВыражениеСГруппировкойМассив, если вам нужно специфическое поведение итогов.
Помните, что СКД — это мощный инструмент, и понимание того, как он обрабатывает выборку данных (SQL-результат запроса), является ключом к созданию точных и профессиональных отчетов.