К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как умножить в запросе 1С: практическое руководство

Как выполнить умножение в запросе 1С: оператор *, ВЫРАЗИТЬ, умножение количества на цену, округление результата и типичные ошибки разработчиков.

Умножение в запросе 1С выполняется стандартным оператором звёздочка (*) прямо в тексте запроса — так же, как в обычной арифметике. Оператор работает в секциях ВЫБРАТЬ, ГДЕ, ИМЕЮЩИЕ, в итогах и в соединениях, позволяя вычислять суммы, цены, коэффициенты и любые производные показатели без постобработки в коде. Это один из самых частых приёмов: например, расчёт суммы строки документа как произведения количества на цену.

Главная сложность — не само умножение, а типы данных. Язык запросов 1С строго относится к разрядности чисел, и при умножении двух полей результат может выйти за допустимую точность или дать ошибку переполнения. Поэтому важно понимать, как платформа обрабатывает типы, когда применять функцию ВЫРАЗИТЬ и как округлять результат.

Ниже разобраны базовый синтаксис, работа с NULL, умножение в группировках и условиях, контроль точности и типичные ошибки. Примеры приведены на языке запросов 1С и подходят для большинства конфигураций на управляемых и обычных формах.

Базовый синтаксис умножения в запросе

Оператор умножения — символ звёздочки (*). Он ставится между двумя числовыми операндами: полями таблицы, константами, параметрами или результатами других выражений. Простейший пример — расчёт суммы по строкам табличной части документа:

ВЫБРАТЬ

РеализацияТовары.Номенклатура КАК Номенклатура,

РеализацияТовары.Количество КАК Количество,

РеализацияТовары.Цена КАК Цена,

РеализацияТовары.Количество * РеализацияТовары.Цена КАК Сумма

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары

ГДЕ

РеализацияТовары.Ссылка = &Ссылка

Умножать можно и на константу, и на параметр запроса. Например, пересчёт количества с учётом коэффициента: Остатки.Количество * &Коэффициент. Параметр передаётся через Запрос.УстановитьПараметр("Коэффициент", 1.18) до выполнения запроса.

Оператор подчиняется стандартному приоритету: умножение и деление выполняются раньше сложения и вычитания. Если порядок вычислений неочевиден, всегда ставьте скобки — это убережёт от трудноуловимых ошибок в формулах вроде Количество Цена + Скидка, где скидка должна применяться до умножения.

bsl
ВЫБРАТЬ Таб.Количество * Таб.Цена КАК Сумма ИЗ Документ.Реализация.Товары КАК Таб

Умножение с параметрами и константами

Когда один из множителей известен заранее — ставка НДС, курс валюты, коэффициент пересчёта упаковок — его удобно передавать параметром. Это делает запрос универсальным: один и тот же текст работает с разными значениями без редактирования.

ВЫБРАТЬ

Продажи.Номенклатура КАК Номенклатура,

Продажи.СуммаОборот * &КурсВалюты КАК СуммаВВалюте

ИЗ

РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи

Константу можно вписать прямо в текст запроса: Таб.Сумма * 0.2. Однако литералы жёстко фиксируют логику — если ставка изменится, придётся править все запросы. Практичнее хранить такие значения в константах конфигурации или функциональных опциях и передавать параметром.

Обратите внимание: параметр должен иметь числовой тип. Если передать строку или значение неопределённого типа, запрос завершится с ошибкой ещё на этапе выполнения. Для надёжности явно приводите значение в коде: Запрос.УстановитьПараметр("Курс", Число(КурсВалюты)).

Контроль типов и точности через ВЫРАЗИТЬ

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

Функция ВЫРАЗИТЬ позволяет явно задать тип результата вычисления:

ВЫБРАТЬ

ВЫРАЗИТЬ(Таб.Количество * Таб.Цена КАК ЧИСЛО(15, 2)) КАК Сумма

Здесь ЧИСЛО(15, 2) означает: всего до 15 цифр, из них 2 — после запятой. Для денежных сумм этого обычно достаточно. Для курсов и коэффициентов, где важна дробная часть, увеличивайте точность — например, ЧИСЛО(15, 4) или ЧИСЛО(15, 6).

Не увлекайтесь избыточной разрядностью: слишком широкий тип замедляет вычисления и увеличивает размер временных таблиц. Подбирайте параметры под реальный диапазон значений — максимальная сумма документа плюс запас на округление.

Умножение и NULL: защита через ЕСТЬNULL

Любая арифметическая операция с NULL даёт NULL. Если цена не заполнена, выражение Количество * Цена вернёт NULL, и сумма «потеряется» — в группировке такие строки просто выпадут из итогов. Это одна из самых частых причин расхождения отчётов.

Защититься помогает функция ЕСТЬNULL, которая подставляет значение по умолчанию:

ВЫБРАТЬ

Таб.Номенклатура КАК Номенклатура,

Таб.Количество * ЕСТЬNULL(Цены.Цена, 0) КАК Сумма

ИЗ

Документ.Заказ.Товары КАК Таб

ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК Цены

ПО Таб.Номенклатура = Цены.Номенклатура

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

Разница между двумя подходами существенна. ЕСТЬNULL вокруг отдельного поля позволяет отличить «цены нет» от «цена равна нулю», если подставить не 0, а другое значение. ЕСТЬNULL вокруг всего произведения проще, но маскирует причину проблемы.

Типичные ошибки
01
Умножение без ЕСТЬNULL — строки с незаполненной ценой выпадают из итогов, отчёт не сходится с обороткой.
02
Отсутствие ВЫРАЗИТЬ — ошибка переполнения или обрезание копеек при умножении полей с большой разрядностью.
03
Передача параметра строкой — запрос падает с ошибкой несоответствия типов ещё до выполнения.
04
Умножение вместо деления при пересчёте курса — результат завышен в разы, проверяйте формулу на контрольном примере.

Умножение в группировках, итогах и условиях

В запросах с СГРУППИРОВАТЬ ПО умножение может применяться двумя способами, и результат принципиально различается. Первый — умножение внутри агрегатной функции: СУММА(Таб.Количество * Таб.Цена). Считается сумма произведений по каждой строке — корректный способ получить итоговую сумму продаж.

Второй — умножение результата агрегата: СУММА(Таб.Количество) * &Курс. Здесь сначала суммируется количество, потом применяется коэффициент. Это подходит для пересчёта итогов в валюту, но не для расчёта суммы по строкам с разными ценами.

Умножение работает и в условиях. В секции ГДЕ можно отфильтровать строки по вычисляемому значению: ГДЕ Таб.Количество Таб.Цена > &МинСумма. В секции ИМЕЮЩИЕ — отфильтровать группы: ИМЕЮЩИЕ СУММА(Таб.Количество Таб.Цена) > 100000. Учтите, что вычисления в ГДЕ выполняются для каждой строки и могут замедлить запрос на больших таблицах.

В секции ИТОГИ умножение напрямую недоступно — итоги считаются по уже выбранным полям. Поэтому вычисляемое поле (например, Сумма) нужно сформировать в ВЫБРАТЬ, а затем указать в итогах: ИТОГИ СУММА(Сумма) ПО ОБЩИЕ.

Сравнение вариантов

СУММА(Количество <em> Цена)

Правильный расчёт суммы, когда у строк разные цены. Умножение выполняется построчно до суммирования.

СУММА(Количество) </em> Курс

Подходит для пересчёта готового итога на единый коэффициент. Не подходит, если множитель различается по строкам.

Умножение в ГДЕ

Позволяет фильтровать по вычисляемому значению, но замедляет запрос на больших таблицах — вычисление идёт для каждой строки.

Практический пример: отчёт по продажам с суммой

Соберём типовую задачу целиком: отчёт по продажам за период с расчётом суммы, защитой от NULL и контролем типов. Запрос обращается к оборотам регистра накопления и дополняет их расчётным полем.

ВЫБРАТЬ

Продажи.Номенклатура КАК Номенклатура,

СУММА(Продажи.КоличествоОборот) КАК Количество,

ВЫРАЗИТЬ(СУММА(ЕСТЬNULL(Продажи.КоличествоОборот, 0) * &СредняяЦена) КАК ЧИСЛО(15, 2)) КАК СуммаОценка

ИЗ

РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , ) КАК Продажи

СГРУППИРОВАТЬ ПО

Продажи.Номенклатура

ИМЕЮЩИЕ

СУММА(Продажи.КоличествоОборот) > 0

Проверьте результат на контрольном примере: возьмите одну номенклатуру, посчитайте произведение вручную и сравните с выводом запроса. Если цифры расходятся — в первую очередь смотрите на NULL в исходных данных и на точность в ВЫРАЗИТЬ.

Для отладки удобно выводить операнды отдельными полями рядом с произведением. Когда видно количество, цену и результат одновременно, причина ошибки находится за секунды. После отладки лишние поля можно убрать.

Порядок действий
  1. 1
    Напишите выражение умножения в секции ВЫБРАТЬ с псевдонимом через КАК.
  2. 2
    Оберните операнды, которые могут быть пустыми, в ЕСТЬNULL(..., 0).
  3. 3
    Задайте тип результата через ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 2)).
  4. 4
    Выполните запрос в консоли запросов на тестовых данных.
  5. 5
    Сверьте результат с ручным расчётом на одной контрольной строке.

Производительность и ограничения

Само по себе умножение — дешёвая операция, и оптимизировать её почти никогда не требуется. Проблемы возникают из контекста: вычисления в условиях соединения или в ГДЕ по большим таблицам, умножение над полями составного типа, лишние вычисления во временных таблицах с миллионами строк.

Если вычисляемое поле используется несколько раз — в выборке, условии и итогах — выгоднее поместить результат во временную таблицу и дальше ссылаться на готовое поле. Это сокращает текст запроса и гарантирует одинаковое значение во всех местах.

Помните об ограничении: язык запросов не умеет вызывать произвольные функции встроенного языка. Если расчёт сложный — с условной логикой, обращениями к нескольким регистрам, нестандартным округлением — возможно, его честнее вынести в код после выполнения запроса или реализовать через ВЫБОР КОГДА...ТОГДА внутри запроса.

Контрольные точки

Как проверить результат

Сумма по контрольной строке
Норма

Совпадает с ручным расчётом количество × цена

Тревожный признак

Расходится — ищите NULL или неверную точность

Итог по группе
Норма

Равен сумме произведений по строкам

Тревожный признак

Меньше ожидаемого — строки с NULL выпали

Тип поля результата
Норма

Число с нужной точностью, копейки на месте

Тревожный признак

Обрезанные дробные значения или ошибка переполнения

Частые вопросы

Можно ли умножать строки или даты в запросе 1С?

Нет. Оператор * работает только с числовыми операндами. Для дат есть специальные функции — РАЗНОСТЬДАТ и ДОБАВИТЬКДАТЕ, а строки в арифметике запроса не участвуют вовсе: попытка умножить строку вызовет ошибку несоответствия типов.

Как округлить результат умножения до двух знаков?

Используйте ВЫРАЗИТЬ(выражение КАК ЧИСЛО(15, 2)) — при приведении типа значение округляется по правилам арифметического округления. Альтернатива — обработка результата в коде функцией Окр() после выполнения запроса.

Почему результат умножения равен NULL, хотя оба поля заполнены?

Один из операндов всё же содержит NULL — чаще всего из-за левого соединения, где для части строк нет соответствия во второй таблице. Проверьте данные, выведя операнды отдельными полями, и оберните проблемное поле в ЕСТЬNULL.

Как умножить поле на значение из другого запроса?

Напрямую нельзя — сначала выполните первый запрос, получите значение в коде и передайте его параметром во второй запрос. Либо объедините данные в одном запросе через соединение или подзапрос, если оба набора данных доступны одновременно.

Работает ли умножение в СКД и динамических списках?

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

Что быстрее: умножить в запросе или в цикле после выборки?

Почти всегда быстрее в запросе: СУБД выполняет арифметику на своей стороне и не гоняет лишние данные. Вычисления в цикле оправданы только для сложной логики, которую невозможно выразить средствами языка запросов.

Итог

Что важно запомнить

Умножение в запросе 1С — это оператор <em> между числовыми операндами. Всегда защищайте выражение от NULL через ЕСТЬNULL, фиксируйте тип результата через ВЫРАЗИТЬ и проверяйте расчёт на контрольном примере. Для итогов используйте СУММА(Количество </em> Цена), а не умножение готовых агрегатов, если множители различаются по строкам.