Разработка и Конфигурация · 12 мин
Как умножить в запросе 1С: практическое руководство
Как выполнить умножение в запросе 1С: оператор *, ВЫРАЗИТЬ, умножение количества на цену, округление результата и типичные ошибки разработчиков.
Умножение в запросе 1С выполняется стандартным оператором звёздочка (*) прямо в тексте запроса — так же, как в обычной арифметике. Оператор работает в секциях ВЫБРАТЬ, ГДЕ, ИМЕЮЩИЕ, в итогах и в соединениях, позволяя вычислять суммы, цены, коэффициенты и любые производные показатели без постобработки в коде. Это один из самых частых приёмов: например, расчёт суммы строки документа как произведения количества на цену.
Главная сложность — не само умножение, а типы данных. Язык запросов 1С строго относится к разрядности чисел, и при умножении двух полей результат может выйти за допустимую точность или дать ошибку переполнения. Поэтому важно понимать, как платформа обрабатывает типы, когда применять функцию ВЫРАЗИТЬ и как округлять результат.
Ниже разобраны базовый синтаксис, работа с NULL, умножение в группировках и условиях, контроль точности и типичные ошибки. Примеры приведены на языке запросов 1С и подходят для большинства конфигураций на управляемых и обычных формах.
Базовый синтаксис умножения в запросе
Оператор умножения — символ звёздочки (*). Он ставится между двумя числовыми операндами: полями таблицы, константами, параметрами или результатами других выражений. Простейший пример — расчёт суммы по строкам табличной части документа:
ВЫБРАТЬ
РеализацияТовары.Номенклатура КАК Номенклатура,
РеализацияТовары.Количество КАК Количество,
РеализацияТовары.Цена КАК Цена,
РеализацияТовары.Количество * РеализацияТовары.Цена КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ГДЕ
РеализацияТовары.Ссылка = &Ссылка
Умножать можно и на константу, и на параметр запроса. Например, пересчёт количества с учётом коэффициента: Остатки.Количество * &Коэффициент. Параметр передаётся через Запрос.УстановитьПараметр("Коэффициент", 1.18) до выполнения запроса.
Оператор подчиняется стандартному приоритету: умножение и деление выполняются раньше сложения и вычитания. Если порядок вычислений неочевиден, всегда ставьте скобки — это убережёт от трудноуловимых ошибок в формулах вроде Количество Цена + Скидка, где скидка должна применяться до умножения.
ВЫБРАТЬ Таб.Количество * Таб.Цена КАК Сумма ИЗ Документ.Реализация.Товары КАК ТабУмножение с параметрами и константами
Когда один из множителей известен заранее — ставка НДС, курс валюты, коэффициент пересчёта упаковок — его удобно передавать параметром. Это делает запрос универсальным: один и тот же текст работает с разными значениями без редактирования.
ВЫБРАТЬ
Продажи.Номенклатура КАК Номенклатура,
Продажи.СуммаОборот * &КурсВалюты КАК СуммаВВалюте
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи
Константу можно вписать прямо в текст запроса: Таб.Сумма * 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 вокруг всего произведения проще, но маскирует причину проблемы.
Умножение в группировках, итогах и условиях
В запросах с СГРУППИРОВАТЬ ПО умножение может применяться двумя способами, и результат принципиально различается. Первый — умножение внутри агрегатной функции: СУММА(Таб.Количество * Таб.Цена). Считается сумма произведений по каждой строке — корректный способ получить итоговую сумму продаж.
Второй — умножение результата агрегата: СУММА(Таб.Количество) * &Курс. Здесь сначала суммируется количество, потом применяется коэффициент. Это подходит для пересчёта итогов в валюту, но не для расчёта суммы по строкам с разными ценами.
Умножение работает и в условиях. В секции ГДЕ можно отфильтровать строки по вычисляемому значению: ГДЕ Таб.Количество Таб.Цена > &МинСумма. В секции ИМЕЮЩИЕ — отфильтровать группы: ИМЕЮЩИЕ СУММА(Таб.Количество Таб.Цена) > 100000. Учтите, что вычисления в ГДЕ выполняются для каждой строки и могут замедлить запрос на больших таблицах.
В секции ИТОГИ умножение напрямую недоступно — итоги считаются по уже выбранным полям. Поэтому вычисляемое поле (например, Сумма) нужно сформировать в ВЫБРАТЬ, а затем указать в итогах: ИТОГИ СУММА(Сумма) ПО ОБЩИЕ.
Сравнение вариантов
Правильный расчёт суммы, когда у строк разные цены. Умножение выполняется построчно до суммирования.
Подходит для пересчёта готового итога на единый коэффициент. Не подходит, если множитель различается по строкам.
Позволяет фильтровать по вычисляемому значению, но замедляет запрос на больших таблицах — вычисление идёт для каждой строки.
Практический пример: отчёт по продажам с суммой
Соберём типовую задачу целиком: отчёт по продажам за период с расчётом суммы, защитой от NULL и контролем типов. Запрос обращается к оборотам регистра накопления и дополняет их расчётным полем.
ВЫБРАТЬ
Продажи.Номенклатура КАК Номенклатура,
СУММА(Продажи.КоличествоОборот) КАК Количество,
ВЫРАЗИТЬ(СУММА(ЕСТЬNULL(Продажи.КоличествоОборот, 0) * &СредняяЦена) КАК ЧИСЛО(15, 2)) КАК СуммаОценка
ИЗ
РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , ) КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Номенклатура
ИМЕЮЩИЕ
СУММА(Продажи.КоличествоОборот) > 0
Проверьте результат на контрольном примере: возьмите одну номенклатуру, посчитайте произведение вручную и сравните с выводом запроса. Если цифры расходятся — в первую очередь смотрите на NULL в исходных данных и на точность в ВЫРАЗИТЬ.
Для отладки удобно выводить операнды отдельными полями рядом с произведением. Когда видно количество, цену и результат одновременно, причина ошибки находится за секунды. После отладки лишние поля можно убрать.
- 1Напишите выражение умножения в секции ВЫБРАТЬ с псевдонимом через КАК.
- 2Оберните операнды, которые могут быть пустыми, в ЕСТЬNULL(..., 0).
- 3Задайте тип результата через ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 2)).
- 4Выполните запрос в консоли запросов на тестовых данных.
- 5Сверьте результат с ручным расчётом на одной контрольной строке.
Производительность и ограничения
Само по себе умножение — дешёвая операция, и оптимизировать её почти никогда не требуется. Проблемы возникают из контекста: вычисления в условиях соединения или в ГДЕ по большим таблицам, умножение над полями составного типа, лишние вычисления во временных таблицах с миллионами строк.
Если вычисляемое поле используется несколько раз — в выборке, условии и итогах — выгоднее поместить результат во временную таблицу и дальше ссылаться на готовое поле. Это сокращает текст запроса и гарантирует одинаковое значение во всех местах.
Помните об ограничении: язык запросов не умеет вызывать произвольные функции встроенного языка. Если расчёт сложный — с условной логикой, обращениями к нескольким регистрам, нестандартным округлением — возможно, его честнее вынести в код после выполнения запроса или реализовать через ВЫБОР КОГДА...ТОГДА внутри запроса.
Как проверить результат
Совпадает с ручным расчётом количество × цена
Расходится — ищите NULL или неверную точность
Равен сумме произведений по строкам
Меньше ожидаемого — строки с NULL выпали
Число с нужной точностью, копейки на месте
Обрезанные дробные значения или ошибка переполнения
Частые вопросы
Можно ли умножать строки или даты в запросе 1С?
Нет. Оператор * работает только с числовыми операндами. Для дат есть специальные функции — РАЗНОСТЬДАТ и ДОБАВИТЬКДАТЕ, а строки в арифметике запроса не участвуют вовсе: попытка умножить строку вызовет ошибку несоответствия типов.
Как округлить результат умножения до двух знаков?
Используйте ВЫРАЗИТЬ(выражение КАК ЧИСЛО(15, 2)) — при приведении типа значение округляется по правилам арифметического округления. Альтернатива — обработка результата в коде функцией Окр() после выполнения запроса.
Почему результат умножения равен NULL, хотя оба поля заполнены?
Один из операндов всё же содержит NULL — чаще всего из-за левого соединения, где для части строк нет соответствия во второй таблице. Проверьте данные, выведя операнды отдельными полями, и оберните проблемное поле в ЕСТЬNULL.
Как умножить поле на значение из другого запроса?
Напрямую нельзя — сначала выполните первый запрос, получите значение в коде и передайте его параметром во второй запрос. Либо объедините данные в одном запросе через соединение или подзапрос, если оба набора данных доступны одновременно.
Работает ли умножение в СКД и динамических списках?
Да, в обоих случаях используется тот же язык запросов. В СКД вычисляемое поле можно дополнительно описать на закладке «Вычисляемые поля», а в динамическом списке произвольный запрос с умножением включается через флаг «Произвольный запрос» — при этом ограничивается интерактивное редактирование данных.
Что быстрее: умножить в запросе или в цикле после выборки?
Почти всегда быстрее в запросе: СУБД выполняет арифметику на своей стороне и не гоняет лишние данные. Вычисления в цикле оправданы только для сложной логики, которую невозможно выразить средствами языка запросов.
Что важно запомнить
Умножение в запросе 1С — это оператор <em> между числовыми операндами. Всегда защищайте выражение от NULL через ЕСТЬNULL, фиксируйте тип результата через ВЫРАЗИТЬ и проверяйте расчёт на контрольном примере. Для итогов используйте СУММА(Количество </em> Цена), а не умножение готовых агрегатов, если множители различаются по строкам.