Как правильно просуммировать поля из разных запросов в СКД и победить NULL

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

При разработке отчетов на схеме компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда необходимо объединить данные из нескольких запросов (наборов данных). Типичный пример: в одном запросе мы получаем данные по продажам и прибыли, во втором — расходы на продажу, в третьем — управленческие расходы. Нам нужно посчитать итоговую чистую прибыль по формуле: Прибыль = ПрибыльУбытокОбычная - РасхНаПродажу - УправРасходы.

Однако при выводе отчета итоговая колонка неожиданно оказывается пустой, либо из нее пропадают данные, как только по какой-то из аналитик отсутствует оборот (например, в текущем месяце не было управленческих расходов). Давайте подробно разберем, почему возникает эта проблема, как работает механизм связи наборов данных и как правильно составить выражение ресурса в СКД, чтобы расчеты всегда сходились.

В чем кроется причина проблемы?

В языке запросов 1С и стандарте SQL любое арифметическое действие со значением NULL возвращает NULL. Если сложить сто тысяч и неопределенность, результатом будет неопределенность:

100 000 - 20 000 - NULL = NULL

Когда вы пытаетесь рассчитать ресурс по формуле:


Сумма(ПрибыльУбытокОбычная) - Сумма(СуммаОборотРасхНаПродажу) - Сумма(СуммаОборотУправРасходы)

И при этом хотя бы по одному из слагаемых (например, по управленческим расходам) за выбранный период не было движений, агрегатная функция Сумма() возвращает NULL. Вся цепочка вычислений рушится, и итоговое поле отображает пустоту.

Многие разработчики пытаются решить эту проблему «в лоб» — прописывая конструкцию ЕСТЬNULL(УправРасходы.СуммаОборот, 0) непосредственно в тексте запроса подчиненного набора данных. Но это не помогает. Почему так происходит?

Дело в том, что когда мы связываем наборы данных на вкладке «Связи наборов данных», СКД объединяет их в собственном процессоре компоновки. Это объединение по своей логике аналогично ЛЕВОМУ СОЕДИНЕНИЮ. Даже если ваш подчиненный запрос вернул ноль, для тех строк главного запроса, по которым нет соответствия в подчиненном, СКД принудительно подставит NULL во все поля подчиненного набора. В итоге обработка NULL внутри текста запроса полностью нивелируется.

---

Решение 1. Использование ЕСТЬNULL в выражении ресурсов (Правильный подход)

Для решения проблемы нам нужно обрабатывать неопределенные значения на уровне расчета итогов (ресурсов) СКД. Давайте проанализируем разницу между двумя вариантами написания функции в ресурсах:

Вариант А (Неправильный):

Сумма(ЕСТЬNULL(СуммаОборотУправРасходы, 0))

В данном случае функция ЕСТЬNULL заменяет пустоту на ноль для каждой детальной записи, а затем СКД пытается их просуммировать. Однако если для текущей группировки в подчиненном наборе данных вообще нет ни одной строки (пустая выборка), сам агрегат Сумма() всё равно вернет NULL, и итоговый расчет снова сломается.

Вариант Б (Правильный и надежный):

ЕСТЬNULL(Сумма(СуммаОборотУправРасходы), 0)

Здесь мы сначала рассчитываем агрегат (сумму). Если записей не было и агрегат вернул NULL, вся конструкция целиком заменяется на 0. Это гарантирует стабильный результат математических операций.

Применим этот подход к нашей задаче. На вкладке «Ресурсы» для итогового поля пропишем выражение:


ЕСТЬNULL(Сумма(ПрибыльУбытокОбычная), 0) 
- ЕСТЬNULL(Сумма(СуммаОборотРасхНаПродажу), 0) 
- ЕСТЬNULL(Сумма(СуммаОборотУправРасходы), 0)

Такой синтаксис гарантирует, что даже при полном отсутствии данных по одной из колонок, расчет будет произведен корректно.

---

Решение 2. Использование Вычисляемых полей

Если выражение ресурса получается слишком громоздким (например, когда суммируется более 5-10 показателей), формулу можно упростить с помощью вычисляемых полей:

  1. Перейдем на вкладку «Вычисляемые поля».
  2. Добавим новое поле, например, УправРасходыЧистые.
  3. В колонке «Выражение» напишем: ЕстьNull(СуммаОборотУправРасходы, 0). СКД обработает это выражение на этапе компоновки до расчета итогов.
  4. На вкладке «Ресурсы» мы сможем использовать простую и лаконичную формулу: Сумма(УправРасходыЧистые).

---

Решение 3. Архитектурный подход (Один запрос вместо связей)

Связи наборов данных в СКД — это ресурсоемкий инструмент. При сложных группировках они могут приводить к «раздваиванию» или потере сумм. Фирма «1С» рекомендует по возможности объединять данные на уровне СУБД в одном запросе.

Вместо связывания трех разных запросов в СКД, спроектируем один запрос, объединяющий таблицы через ОБЪЕДИНЕНИЕ ВСЕХ во временных таблицах:


ВЫБРАТЬ
    Продажи.Организация КАК Организация,
    Продажи.СуммаОборот КАК Прибыль,
    0 КАК РасходыПродажи,
    0 КАК РасходыУправленческие
ПОМЕСТИТЬ ВТ_Данные
ИЗ
    РегистрНакопления.Продажи.Обороты КАК Продажи

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Расходы.Организация,
    0,
    Расходы.СуммаОборот,
    0
ИЗ
    РегистрНакопления.РасходыНаПродажи.Обороты КАК Расходы

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Управ.Организация,
    0,
    0,
    Управ.СуммаОборот
ИЗ
    РегистрНакопления.УправленческиеРасходы.Обороты КАК Управ
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Данные.Организация КАК Организация,
    СУММА(ВТ_Данные.Прибыль) КАК Прибыль,
    СУММА(ВТ_Данные.РасходыПродажи) КАК РасходыПродажи,
    СУММА(ВТ_Данные.РасходыУправленческие) КАК РасходыУправленческие
ИЗ
    ВТ_Данные КАК ВТ_Данные
СГРУППИРОВАТЬ ПО
    ВТ_Данные.Организация

При таком подходе СКД получит плоскую таблицу без значений NULL (вместо них будут реальные нули), и стандартный расчет ресурсов отработает идеально без дополнительных проверок.

---

Ловушка кэширования СКД (Важный нюанс)

Часто разработчики сталкиваются с феноменом: «Я написал формулу с ЕСТЬNULL в ресурсах, но отчет всё равно выводит пустоту!».

Платформа 1С активно кэширует схемы компоновки данных и структуру отчетов в рамках текущего сеанса пользователя. Если вы внесли изменения в ресурсы СКД и просто нажали кнопку «Сформировать», платформа может запустить отчет по старому алгоритму из кэша. Чтобы изменения вступили в силу, выполните следующие действия:

Именно сброс кэша (перезапуск платформы) часто является финальным шагом, после которого верные формулы ресурсов начинают рассчитываться корректно.

← На главную