Разработка отчетов в Системе компоновки данных (СКД) часто сопряжена с трудностями при вычислении разностей между показателями, особенно если эти показатели приходят из разных источников или наборов данных. Типичный пример — расчет финансового результата как разницы между продажами и расходами. Нередко программисты сталкиваются с тем, что отчет выводит пустые строки, некорректно суммирует итоги или вовсе обнуляет результат. В этой статье мы подробно разберем причины таких ошибок и методы их решения.
Проанализируем ситуацию, когда данные о продажах и расходах находятся в разных наборах данных (например, два разных запроса). Основная причина некорректных расчетов кроется в природе обработки значений NULL. В языке запросов и в выражениях СКД любая арифметическая операция с неопределенным значением (например, 100 - NULL) всегда дает в результате NULL (пустоту).
Рассмотрим по шагам, как избежать типичных ошибок и настроить корректный расчет разностей в ресурсах отчета.
Одной из первых проблем, с которой сталкиваются разработчики, является влияние глобальных отборов на расчет итогов. Если мы устанавливаем отбор на вкладке Настройки, СКД применяет его к уже полученному результату. Это может привести к тому, что данные, необходимые для расчета разницы (например, себестоимость), будут отсечены, и итоговая формула выдаст неверный результат.
Выясним причину: когда мы ограничиваем данные в самом запросе (вкладка Условия в конструкторе запроса), мы гарантируем, что в компоновку попадут только нужные нам записи. Например, если нам нужно исключить оплаты поставщикам из общих расходов, лучше сделать это непосредственно в тексте запроса:
ВЫБРАТЬ
Продажи.СуммаОборорт КАК СуммаПродаж,
0 КАК СуммаРасход
ИЗ
РегистрНакопления.Продажи.Обороты КАК Продажи
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
0,
Расходы.Сумма
ИЗ
Документ.РасходныйКассовыйОрдер КАК Расходы
ГДЕ
Расходы.ВидОперации <> ЗНАЧЕНИЕ(Перечисление.ВидыОперацийРКО.ОплатаПоставщику)
Такой подход позволяет подготовить «чистые» данные для последующей агрегации в СКД.
Рассмотрим подробнее механизм вычисления ресурсов. Распространенная ошибка — создание вычисляемого поля с формулой СуммаПродаж - СуммаРасход и последующее суммирование этого поля на вкладке Ресурсы. Правильный подход требует иного порядка действий:
ФинансовыйРезультат. Поле выражения в списке вычисляемых полей можно оставить пустым.ЕСТЬNULL.Проанализируем пример правильной формулы ресурса:
Сумма(ЕСТЬNULL(СуммаПродаж, 0)) - Сумма(ЕСТЬNULL(СуммаРасход, 0))
Почему это важно? Если мы сначала вычтем поля, а потом просуммируем, то при отсутствии продаж в какой-то из группировок (где есть только расходы), вся строка станет пустой. Используя агрегацию Сумма() для каждого слагаемого отдельно, мы заставляем СКД сначала собрать все данные по группировке, заменить пустоты нулями и только потом выполнить вычитание.
Если данные о продажах и расходах хранятся в разных наборах данных (например, НаборДанныхПродажи и НаборДанныхРасходы), они должны «увидеть» друг друга. Для этого необходимо правильно настроить вкладку Связи наборов данных.
Посмотрим на ключевые моменты настройки связей:
Как отметил автор темы, данные нужно группировать так, чтобы они соответствовали друг другу. Если в одном наборе данные детализированы до регистратора, а в другом — только до дня, корректно сопоставить их в одной строке будет сложно без потери точности.
В СКД на вкладке Ресурсы есть колонка Рассчитывать по.... Рассмотрим ситуацию, когда финансовый результат должен считаться по-разному для детальных записей и для итогов по иерархии.
Если оставить это поле пустым, СКД будет применять формулу ко всем уровням группировок. Однако, если расчет сложный, мы можем добавить поле в ресурсы несколько раз:
Выясним причину появления пустых строк в финансовом результате. Если в колонке «Расход» стоит число, а в колонке «Результат» — пусто, это однозначный сигнал о пропущенной функции ЕСТЬNULL. Проанализируем ситуацию: СКД пытается выполнить операцию 1000 - NULL. Математически это неопределенность. Всегда оборачивайте поля ресурсов в проверку на NULL, особенно при работе с левыми соединениями или разными наборами данных.
Важный совет: старайтесь отдавать в СКД максимально «плоские» и детальные данные, а выполнение всех группировок и итоговых расчетов доверяйте самому механизму компоновки. СКД оптимизирована для работы с итогами гораздо лучше, чем вложенные запросы с предварительными итогами внутри текста ВЫБРАТЬ... ИТОГИ ПО.
Подводя итог, для исправления «неправильного» вычитания в СКД выполним следующие действия:
ЕСТЬNULL в формулах ресурсов.Сумма() внутри выражений ресурсов для каждого операнда отдельно.