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