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