Вычисляемое поле в СКД: от простой формулы до нарастающего итога
Содержание
Вычисляемое поле добавляют в конструкторе схемы компоновки данных на закладке Вычисляемые поля: задаёте путь к данным, выражение и заголовок — и в отчёте появляется новая колонка. Второй путь быстрее и не требует правки конфигурации: пользовательское поле прямо в настройках готового отчёта.
Подвох в том, что формула в запросе и формула в вычисляемом поле считаются по-разному. Первая выполняется на сервере СУБД до выборки, вторая — уже после, для каждой записи компоновки. Перепутать их — значит получить пустые ячейки, деление на ноль или отчёт, который заметно тормозит на большой выборке. Разберёмся, как настроить вычисляемое поле в СКД правильно и чем отличаются доступные способы его добавить.
Что делает вычисляемое поле и когда оно нужнее запроса
Поле запроса берётся из базы: ВЫБРАТЬ Цена * Количество КАК Сумма. СУБД считает его один раз, по нему можно группировать и отбирать быстро.
Вычисляемое поле СКД работает иначе. Его выражение применяется к уже полученному набору данных — к каждой детальной записи и к каждой группировке отдельно. Поэтому в нём доступны то, чего нет в запросе: функции компоновки вроде ВычислитьВыражение, обращение к ресурсам и к соседним группировкам.
Вывод простой:
- 🧮 Значение можно получить прямо в запросе — считайте его в запросе. Это быстрее, и по такому полю доступны отбор и группировка на уровне СУБД.
- 📊 Значение зависит от итогов, соседних строк или нарастающего результата — это вычисляемое поле СКД. В запросе такого не выразить.
Классические задачи именно для вычисляемого поля: процент строки от общего итога, нарастающий итог, ранг, «склейка» ФИО или адреса в одну строку на этапе вывода, подстановка текста по условию.
Важная деталь контекста. Одно и то же вычисляемое поле СКД пересчитывает в детальных записях и отдельно в каждой строке-группировке. В детализации оно работает со значениями конкретной записи, в итоговой строке — со значениями этой группировки. Поэтому результат в подвале группы не обязан равняться сумме строк: если поле считает, скажем, среднюю цену, в итоге будет среднее по группе, а не сумма средних по строкам. Это свойство компоновки, а не ошибка, и его стоит держать в голове при проверке цифр.
Три способа добавить вычисляемое поле в СКД
Способ зависит от того, кто и где правит отчёт.
1. На закладке «Вычисляемые поля» схемы. Открываете макет с типом «Схема компоновки данных», переходите на закладку Вычисляемые поля, добавляете строку. Заполняете:
Путь данных— имя поля латиницей или кириллицей без пробелов (например,Процент);Заголовок— как колонка подпишется в отчёте;Выражение— собственно формула на языке выражений СКД;Тип значения— задайте явно, если планируете сортировку или особое форматирование по этому полю.
После этого поле нужно вынести в настройки: на закладке Настройки добавить его в Выбранные поля. Само по себе определение поля в схеме колонку в отчёте не показывает.
2. Пользовательское поле в настройках отчёта. Этот способ доступен конечному пользователю, без Конфигуратора. В форме настроек отчёта открываете Пользовательские поля (в типовых отчётах — через меню Ещё → Изменить вариант или Настройки), добавляете Новое поле выражение. У такого поля два выражения:
Выражение детальных записей— значение в строках-детализациях;Выражение итоговых записей— значение в строках-итогах (группировках).
Если заполнить только первое, в итоговых строках поле останется пустым. Это частая причина «пропавших» значений в подвале группировки.
3. Поле-выбор (ВЫБОР … КОГДА). Там же, рядом с полем-выражением, есть Новое поле выбор — визуальный конструктор условий без ручного набора ВЫБОР КОГДА … ТОГДА … КОНЕЦ. Удобно, когда значение зависит от набора условий, а писать выражение вручную не хочется.
ВЫБРАТЬ … КАК Поле. Быстрее и работает на стороне СУБД.ВычислитьВыражение.Язык выражений СКД: операторы и функции
Выражение пишется на языке выражений системы компоновки данных. Он близок к встроенному языку 1С, но это не он — часть привычных методов здесь недоступна.
Что точно работает:
- арифметика
+ - * /, сравнения= <> > < >= <=; - логика
И,ИЛИ,НЕ; - условие
ВЫБОР КОГДА Условие ТОГДА Значение1 ИНАЧЕ Значение2 КОНЕЦ; - обработка пустых значений
ЕСТЬNULL(Поле, 0); - агрегатные функции
Сумма(),Количество(),Среднее(),Минимум(),Максимум(); - строковые и датовые функции:
Строка(),Формат(),Год(),Месяц(),НачалоПериода(),ПредставлениеПериода().
Простые примеры:
// Полное имя из трёх полей
Фамилия + " " + Имя + " " + Отчество
// Сумма строки без деления на ноль
ВЫБОР КОГДА Количество = 0 ТОГДА 0 ИНАЧЕ Выручка / Количество КОНЕЦ
// Текстовая метка по условию
ВЫБОР КОГДА ОстатокДолга > 0 ТОГДА "Должник" ИНАЧЕ "Оплачено" КОНЕЦ
К полю обращаются по имени так, как оно задано в наборе данных или в псевдониме запроса. Если поле вложено в таблицу (Товары.Номенклатура), путь пишется через точку.
Ещё пара моментов, на которых спотыкаются чаще всего:
- Ссылочные поля. В таблицу попадает ссылка, а не её текст. Чтобы вывести наименование, берите реквизит через точку (
Номенклатура.Наименование) либо получайте представление функциейПредставление(Номенклатура). Складывать ссылку со строкой напрямую нельзя. - Типы в арифметике. Сложение строки и числа без приведения даёт ошибку. Число превращают в строку через
Строка()или собирают текст шаблоном, а не «плюсом». - Дата как период. Для группировки по месяцу или кварталу удобно считать
НачалоПериода(Дата, "Месяц"), а подписывать —ПредставлениеПериода(НачалоПериода(Дата, "Месяц"), КонецПериода(Дата, "Месяц")).
Отдельный приём — агрегат с условием. Он помогает посчитать «количество только оплаченных» без отдельного ресурса:
// Доля оплаченных заказов в группировке
Количество(ВЫБОР КОГДА Статус = "Оплачен" ТОГДА 1 КОНЕЦ)
/ Количество(Ссылка) * 100
Внутри ВЫБОР без ветки ИНАЧЕ неподходящие строки дают NULL и в счёт Количество не попадают — ровно то, что нужно.
Нарастающий итог и процент от общего: функция ВычислитьВыражение
Главный инструмент вычисляемых полей — функция ВычислитьВыражение. Она считает выражение в контексте другой группировки: общего итога, текущей группировки от первой записи до текущей и так далее.
Процент строки от общего итога. Делим значение записи на грандтотал:
Выручка / ВычислитьВыражение("Сумма(Выручка)", "ОбщийИтог") * 100
Второй параметр "ОбщийИтог" говорит СКД взять сумму по всему отчёту, а не по текущей группировке. Чтобы не словить деление на ноль на пустом отчёте, оберните знаменатель в ВЫБОР КОГДА … КОНЕЦ.
Нарастающий итог. Считаем сумму от первой записи группировки до текущей:
ВычислитьВыражение("Сумма(Выручка)", "", "Группировка", "Первая", "Текущая")
Здесь параметры — выражение, имя группировки (пусто = текущая), тип расчёта и границы Первая/Текущая. Полный список параметров и их значения смотрите в синтакс-помощнике Конфигуратора по функции ВычислитьВыражение — там же описаны Предыдущая, Следующая и числовые смещения для скользящих итогов.
Старую функцию Вычислить() с одним аргументом трогать не нужно: она оставлена для совместимости, в новых отчётах используют ВычислитьВыражение.
ВычислитьВыражение по большой группировке с сортировкой считается для каждой строки заново. На выборках в десятки тысяч строк это ощутимо замедляет вывод — см. раздел о производительности.
Практический пример: поле с условием, итогом и форматированием
Соберём колонку «Доля в обороте, %» с округлением и прочерком вместо нуля. Выражение вычисляемого поля:
ВЫБОР
КОГДА ВычислитьВыражение("Сумма(СуммаПродаж)", "ОбщийИтог") = 0
ТОГДА 0
ИНАЧЕ СуммаПродаж / ВычислитьВыражение("Сумма(СуммаПродаж)", "ОбщийИтог") * 100
КОНЕЦ
Дальше настраиваем вывод:
- У поля в схеме задайте
Тип значения→Число, длина и точность под проценты (например, 5 и 2). - На закладке
Настройки→Условное оформлениедобавьте оформление: при значении поля= 0выводить текст—. Так ноль не загромождает таблицу. - Вынесите поле в
Выбранные поляи, если нужно, разрешите сортировку по нему.
Результат: колонка показывает долю каждой строки в общем обороте, итог по группировке считается автоматически, пустые доли заменяются прочерком. Всё это — без единой строки в модуле.
Второй частый запрос — отклонение от среднего. Покажем, насколько продажи строки выше или ниже среднего по всему отчёту:
СуммаПродаж - ВычислитьВыражение("Среднее(СуммаПродаж)", "ОбщийИтог")
Положительное число — строка выше среднего, отрицательное — ниже. Через условное оформление такие значения удобно подсветить: отрицательные — красным, положительные — зелёным. Оформление настраивается там же, на закладке Условное оформление, с отбором по самому вычисляемому полю.
Почему вычисляемое поле пустое или считает неверно
Чаще всего дело не в формуле, а в данных или в настройке вывода.
Выбранные поля на закладке «Настройки». Определение в схеме только описывает поле, показывает его — настройка.Выражение детальных записей. Добавьте Выражение итоговых записей.ЕСТЬNULL(Поле, 0).ВЫБОР КОГДА Знаменатель = 0 ТОГДА 0 ИНАЧЕ … КОНЕЦ.Тип значения. Укажите тип в схеме — тогда поле станет доступно для упорядочивания.Ещё одна ловушка — путаница между вычисляемым полем и ресурсом. Ресурс агрегирует (суммирует, считает) значение по группировкам автоматически. Вычисляемое поле само по себе ничего не агрегирует: в группировке оно пересчитывает своё выражение. Если нужна именно сумма по группе — заводите ресурс, а в вычисляемом поле уже используйте его результат.
Как не посадить производительность отчёта
Главное правило: всё, что можно посчитать в запросе, считайте в запросе. Поле запроса обрабатывается СУБД и индексами, вычисляемое поле — построчно уже на выводе.
Что замедляет отчёт:
- 🐢
ВычислитьВыражениес сортировкой по большой группировке — для каждой строки идёт отдельный проход. - 🐢 Отбор по вычисляемому полю. В запросе отбор отсекает строки до выборки, а по вычисляемому полю фильтр применяется уже после получения всех данных — лишний объём гоняется зря.
- 🐢 Тяжёлые строковые операции и вложенные
ВЫБОРна каждой детальной записи при десятках тысяч строк.
Практический приём: выносите фильтры и соединения в запрос, а в вычисляемом поле оставляйте только то, что принципиально требует контекста компоновки — проценты, нарастающие итоги, ранги. Если по полю нужен отбор, подумайте, нельзя ли получить то же значение в запросе и фильтровать там.
Есть и обратная сторона. Простые выражения вроде склейки ФИО или метки по условию стоят почти ничего — их спокойно оставляют в вычисляемом поле, даже если формально их можно было бы завести и в запросе. Удаление лишних полей из Выбранные поля и отказ от неиспользуемых группировок дают больший выигрыш, чем перенос одной короткой формулы в запрос. Оптимизировать имеет смысл то, что реально тормозит на вашей выборке, а не каждую строку подряд.
Проверить, где отчёт проводит время, помогает замер времени формирования на реальном объёме данных с включённой и выключенной тяжёлой колонкой: разница сразу покажет, стоит ли эта колонка своих секунд или её логику пора переносить в запрос.
Частые вопросы
Чем вычисляемое поле отличается от ресурса?
Можно ли отобрать отчёт по вычисляемому полю?
Отбор в настройках. Но фильтр сработает уже после выборки, на стороне компоновки, а не СУБД. Если данных много, выгоднее получить значение в запросе и фильтровать там.Почему функция из встроенного языка не работает в выражении?
Чем пользовательское поле отличается от поля в схеме?
Как сделать нарастающий итог в отчёте?
ВычислитьВыражение, где границы расчёта заданы как от первой записи до текущей. Точный набор параметров приведён в синтакс-помощнике по этой функции.