При работе с Системой Компоновки Данных (СКД) в 1С разработчики и пользователи часто сталкиваются с ситуацией, когда агрегатные функции, такие как Сумма() или Среднее(), примененные к ресурсам отчета, возвращают значения, которые кажутся некорректными или нелогичными по сравнению с видимыми данными. Например, среднее значение может быть отрицательным, хотя все исходные цены положительны, или сумма значительно отличается от ожидаемой. Давайте рассмотрим эту проблему подробнее и разберем основные причины такого поведения, а также методы диагностики и устранения.
Типичная ситуация, как описано в исходной проблеме, возникает, когда для группировки «Номенклатура» требуется вывести Среднее(ЦенаНачальныйОстаток), но результат оказывается явно неверным, например, -4.91, или Сумма(ЦенаНачальныйОстаток) также дает неожиданные числа. Ощущение, что СКД «считает что-то не то», или включает в расчет строки, не попадающие в отчет, часто оказывается верным, особенно если требуется сравнить остатки и цены товаров между разными базами данных.
Дублирование данных из-за соединений в запросе.
Это одна из наиболее распространенных причин. Если в схеме СКД вы используете несколько наборов данных или выполняете соединения (ЛЕВОЕ СОЕДИНЕНИЕ, ВНУТРЕННЕЕ СОЕДИНЕНИЕ и т.д.) таблиц, то одна запись из основной таблицы может получить несколько соответствующих записей из присоединенной таблицы. В результате, до агрегации, количество строк, поступающих на вход агрегатной функции, увеличивается. Значение поля ЦенаНачальныйОстаток, которое могло быть уникальным для исходной строки, будет учтено несколько раз для каждой строки, порожденной соединением. Отчет на СКД будет суммировать или усреднять эти дублированные значения, что приводит к неверному итогу. Например, если исходная запись имеет цену 100, а после соединения она дублируется 5 раз, то сумма по этой записи станет 500 вместо 100.
Нарушение последовательности проведения документов и "минусы" в регистрах.
Поле ЦенаНачальныйОстаток, как и другие показатели начальных остатков или себестоимости, критически зависит от правильной хронологической последовательности проведения документов. Если в учете были нарушения последовательности, например, документ прихода проведен после документа расхода за тот же период, это может привести к образованию "минусов" в движениях регистров. Поиск непроведенных документов с движениями поможет быстро выявить такие аномалии. Даже если по итогам периода минусы закрываются, промежуточные расчеты могут быть искажены. СКД будет оперировать теми данными, которые фактически находятся в регистрах, и если эти данные содержат "минусы" или некорректные остатки из-за нарушения последовательности, то и агрегатные функции будут работать с ними, выдавая неверные результаты.
Особенности применения отборов в СКД.
СКД по умолчанию может сначала выполнить агрегацию данных на уровне набора данных (или запроса к базе данных), а уже затем применить отборы и условия, которые вы определили в настройках отчета. Это означает, что если у вас есть отбор, который скрывает часть строк на этапе вывода отчета, среднее или сумма все равно могли быть рассчитаны по всем исходным строкам, включая те, что не попали в видимую часть отчета. Такой механизм может привести к тому, что Количество() вернет большое число строк, хотя визуально их гораздо меньше.
Неверные настройки группировок и детальных записей.
Важно понимать, на каком уровне СКД выполняет агрегацию. Если агрегатная функция указана для ресурса, но нет соответствующей группировки, или группировка не включает все необходимые поля для уникальности записей, результат может быть неверным. Детальные записи (ДетальныеЗаписи) показывают самые низкоуровневые данные, которые используются для агрегации. Если агрегация "схлопывает" строки, которые должны быть уникальными, это может привести к неверным средним и суммам.
Ошибки в выражениях агрегации и настройках ресурсов СКД.
Необходимо тщательно проверить само выражение для расчета Среднее(ЦенаНачальныйОстаток) или Сумма(ЦенаНачальныйОстаток). Убедитесь, что оно ссылается на правильное поле и что само поле содержит числовые данные. Иногда в поле могут попадать NULL значения, которые по-разному обрабатываются агрегатными функциями. Также на вкладке "Ресурсы" в схеме компоновки данных для каждого ресурса можно указать не только функцию агрегации, но и поля, по которым эта агрегация должна производиться. Неправильно настроенные ресурсы могут игнорировать группировки или, наоборот, агрегировать данные на слишком высоком уровне.
Для выявления и устранения причин некорректного расчета агрегатных функций в СКД мы рекомендуем действовать последовательно. Вот шаги, которые помогут вам локализовать проблему:
Начнем с самого фундаментального: посмотрим на сырые данные, которые СКД получает перед агрегацией. Такой быстрый анализ данных позволит нам понять, есть ли дублирование строк или некорректные значения до того, как к ним применятся агрегатные функции.
Полностью уберите все группировки из отчета. В настройках отчета перейдите на вкладку "Структура" и удалите все элементы, кроме "Детальные записи". Если у вас нет "Детальных записей", добавьте их. Убедитесь, что в группировках полей нет ничего лишнего, особенно регистраторов, которые могут влиять на количество строк при агрегации. Наша цель — увидеть максимально "плоский" список данных, который является источником для всех последующих расчетов.
Сформируйте отчет и внимательно проанализируйте полученные строки. Если вы видите, что поле ЦенаНачальныйОстаток для одной и той же номенклатуры (или другого уникального набора измерений) повторяется несколько раз, это прямо указывает на дублирование данных. Именно эти дубликаты и приводят к искажению сумм и средних.
Также обратите внимание на количество строк, которые вы видите, и сравните его с ожидаемым. Если автор темы столкнулся с тем, что Количество(ЦенаНачальныйОстаток) возвращает 23, хотя он видит только 9 документов, это яркий признак дублирования.
Используйте функцию Количество(Различные ...). Чтобы точно определить, есть ли дублирование и сколько уникальных значений на самом деле, добавьте в ресурсы отчета поле с выражением типа:
Количество(Различные Номенклатура)
Количество(Различные Регистратор)
Если Количество(Различные Регистратор) значительно меньше, чем просто Количество(Регистратор), это подтверждает наличие дублирующих строк, порожденных, скорее всего, соединениями в запросе.
Если вы обнаружили дублирование на этапе детальных записей, следующим шагом будет анализ запроса, который формирует набор данных СКД. Чаще всего дублирование возникает из-за:
Некорректных соединений. Например, если вы присоединяете таблицу, которая имеет отношение "один-ко-многим" к вашей основной таблице, но не используете агрегацию или группировку на уровне запроса для этой присоединенной таблицы. Процессор схемы запроса поможет наглядно разобрать структуру таких соединений. Чтобы избежать дублирования, вы можете:
Использовать подзапросы для предварительной агрегации данных из "многочисленной" таблицы до соединения с основной.
Тщательно выбирать поля для соединения. Иногда достаточно добавить уникальный идентификатор для соединения, а не несколько полей.
Если данные из присоединенной таблицы нужны для отбора, но не для вывода или агрегации, рассмотрите возможность использования СУЩЕСТВУЕТ или НЕ СУЩЕСТВУЕТ вместо прямого соединения.
Виртуальные таблицы. При использовании виртуальных таблиц, таких как остатки и обороты, убедитесь, что правильно указаны параметры и измерения. Иногда неправильный набор измерений может привести к избыточному количеству строк.
Особенно для полей, связанных с остатками и ценами (например, ЦенаНачальныйОстаток), критически важна правильная последовательность проведения документов. Нарушения последовательности могут привести к нелогичным остаткам и, как следствие, к неверным расчетам в отчете.
Воспользуйтесь встроенными инструментами. В конфигурации 1С:Комплексная автоматизация (КА 2.5.17) существуют регламентные операции и обработки для проверки и восстановления последовательности проведения документов (например, "Проведение по партиям", "Восстановление последовательности взаиморасчетов"). Регулярно запускайте их, особенно если подозреваете проблемы с учетом.
Проверьте движения регистров. Откройте стандартные отчеты по регистрам, из которых берутся данные для ЦенаНачальныйОстаток, и проверьте наличие "минусов" в течение периода. Даже если конечное сальдо верное, промежуточные отрицательные остатки могут искажать расчеты.
Если проблема в том, что СКД агрегирует данные до применения отборов, у нас есть несколько способов это исправить:
Применяйте отборы на этапе выборки данных. Самый надежный способ — включить условия отбора непосредственно в текст запроса, который формирует набор данных СКД. Это гарантирует, что агрегация будет производиться только по уже отфильтрованным данным.
Используйте условные выражения в агрегатных функциях. Если отбор нужно применить после выборки, но до агрегации, вы можете использовать конструкцию ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ 0 КОНЕЦ внутри агрегатной функции. Например, вместо Сумма(ЦенаНачальныйОстаток), можно написать:
Сумма(ВЫБОР КОГДА Номенклатура.ВидНоменклатуры = &ПараметрВидНоменклатуры ТОГДА ЦенаНачальныйОстаток ИНАЧЕ 0 КОНЕЦ)
В этом случае суммироваться будут только те значения, которые соответствуют условию, а для остальных будет подставляться 0 (или NULL, если это требуется для логики среднего, где NULL игнорируются).
Установите период расчета ресурсов. Для ресурсов в СКД можно явно указать, по каким полям они должны рассчитываться, и как должны применяться отборы. На вкладке "Ресурсы" для поля ЦенаНачальныйОстаток убедитесь, что свойства "Рассчитывать по" и "Автоматически рассчитывать по" настроены корректно относительно ваших группировок.
Необходимо убедиться, что ресурсы в СКД настроены правильно. Перейдите на вкладку "Ресурсы" в вашей схеме компоновки данных. Для поля, по которому вы считаете агрегатную функцию (в нашем случае ЦенаНачальныйОстаток):
Проверьте выражение. Убедитесь, что выражение агрегации написано без ошибок, например, Среднее(ЦенаНачальныйОстаток) или Сумма(ЦенаНачальныйОстаток). Если поле является строковым или имеет смешанный тип, функция может работать некорректно.
Свойства агрегации. В свойствах ресурса убедитесь, что не установлены специфические настройки, которые могут игнорировать ваши группировки или, наоборот, приводить к излишнему агрегированию. По умолчанию, СКД достаточно умна, чтобы применять агрегацию к текущему уровню группировки, но иногда эти настройки могут быть изменены.
Использование различных параметров агрегатных функций. СКД позволяет использовать разные аргументы для агрегатных функций. Например, для Сумма() можно указывать поля, по которым она должна производиться. Проверьте, соответствует ли это вашей задаче. Если в агрегатную функцию необходимо передать конкретные поля для группировки или учета уникальности, это может выглядеть так:
МоеПоле Сумма(МоеПоле) МоеПоле
Этот синтаксис указывает СКД, что агрегация Сумма(МоеПоле) должна производиться с учетом уникальности по МоеПоле. В большинстве случаев, однако, СКД сама справляется с определением уровня агрегации на основе заданных группировок.
Для глубокого анализа проблемы, особенно в сложных отчетах, мы рекомендуем использовать отладчик СКД. Это позволяет пошагово проследить, как СКД формирует наборы данных, применяет отборы, выполняет агрегацию и строит макет отчета. Вы можете:
Сохранить схему компоновки данных в файл. Это позволит нам получить XML-представление схемы и проанализировать ее вручную или с помощью специализированных инструментов.
Выгружать промежуточные данные. Во время отладки можно выгружать промежуточные таблицы, которые формирует СКД на разных этапах, чтобы увидеть, на каком именно этапе происходит искажение или дублирование данных.
Создать упрощенный отчет. Иногда полезно создать отдельный, максимально простой отчет, который будет повторять проблемную часть исходного отчета (например, только один набор данных и одна группировка с проблемным ресурсом). Это помогает локализовать источник ошибки, исключив влияние других элементов сложного отчета.
Таким образом, некорректные суммы и средние значения в отчетах СКД редко являются ошибкой самой платформы. Чаще всего проблема кроется в том, какие данные получает на вход агрегатная функция. Это может быть связано с дублированием данных в запросе, нарушением логики учета (последовательность документов), некорректным применением отборов или неправильной настройкой ресурсов и группировок в самой СКД. Системный подход к диагностике, начиная с анализа детальных записей и заканчивая отладкой запросов, поможет нам найти и устранить причину некорректного поведения отчета.