Работа с запросами в 1С:Предприятие — одна из ключевых задач разработчика. Часто требуется не просто получить данные, а произвести над ними вычисления: посчитать сумму с учётом количества, пересчитать цены в другую валюту или вычислить проценты. Умножение в запросах 1С — базовая операция, но её синтаксис имеет нюансы, которые важно учитывать, чтобы избежать ошибок выполнения или некорректных результатов.
В этой статье разберём все способы умножения в запросах: от элементарных арифметических выражений до сложных конструкций с группировкой, условными операторами и работой с виртуальными таблицами. Особое внимание уделим типичным ошибкам, которые допускают даже опытные программисты, например, умножение полей с разными типами данных без явного приведения или игнорирование особенностей работы с NULL.
Материал будет полезен как начинающим разработчикам, которые только осваивают язык запросов, так и специалистам, желающим систематизировать знания. Все примеры приведены для актуальных версий платформы 1С:Предприятие 8.3 (включая последние релизы) и протестированы на реальных конфигурациях.
Базовый синтаксис умножения в запросах 1С
Самый простой способ умножить значения в запросе — использовать арифметическое выражение прямо в списке полей. Синтаксис интуитивно понятен:
ВЫБРАТЬ
Товары.Наименование КАК Товар,
Товары.Цена * Товары.Количество КАК Сумма
ИЗ
Справочник.Товары КАК Товары
Здесь поле Сумма будет содержать результат умножения цены на количество для каждого товара. Важно помнить два ключевых правила:
- 🔢 Типы данных: оба операнда должны быть числовыми (или приводимы к числу). Умножение строки на число вызовет ошибку.
- 📊 NULL-значения: если хотя бы одно из полей содержит
NULL, результат тоже будетNULL. Это часто становится причиной неожиданных пустых результатов.
Для явного приведения типов используйте функцию ВЫРАЗИТЬ():
ВЫБРАТЬ
ВЫРАЗИТЬ(Документ.СуммаДокумента КАК ЧИСЛО(15, 2)) * 1.2 КАК СуммаСНДС
Если в результате умножения получаете NULL, проверьте исходные данные на наличие пустых значений с помощью конструкции ЕСТЬNULL(Поле, 0).
Умножение с группировкой данных
Часто требуется умножить значения после группировки, например, посчитать общую сумму по группе товаров. В этом случае умножение выполняется в разделе ИТОГИ или с использованием агрегатных функций:
ВЫБРАТЬ
Товары.Категория КАК Категория,
СУММА(Товары.Цена * Товары.Количество) КАК ОбщаяСумма
ИЗ
Справочник.Товары КАК Товары
СГРУППИРОВАТЬ ПО
Товары.Категория
Обратите внимание на порядок операций: сначала выполняется умножение для каждой записи, а затем — суммирование по группам. Если требуется умножить уже сгруппированные данные, используйте вложенные запросы:
ВЫБРАТЬ
Группы.Категория,
Группы.ОбщаяСумма * 1.1 КАК СуммаСНаценкой
ИЗ
(
ВЫБРАТЬ
Товары.Категория КАК Категория,
СУММА(Товары.Цена * Товары.Количество) КАК ОбщаяСумма
ИЗ
Справочник.Товары КАК Товары
СГРУППИРОВАТЬ ПО
Товары.Категория
) КАК Группы
Умножение с условными операторами
В реальных задачах часто требуется умножать значения с учётом условий. Например, применить скидку только к определённой категории товаров. Для этого используйте конструкцию ВЫБОР КОГДА:
ВЫБРАТЬ
Товары.Наименование,
ВЫБОР
КОГДА Товары.Категория = &АкционныеТовары
ТОГДА Товары.Цена Товары.Количество 0.9
ИНАЧЕ Товары.Цена * Товары.Количество
КОНЕЦ КАК СуммаСоСкидкой
Альтернативный вариант — использовать логические выражения прямо в арифметическом выражении:
ВЫБРАТЬ
Товары.Наименование,
Товары.Цена Товары.Количество (1 - (Товары.Скидка / 100)) КАК Сумма
⚠️ Внимание: При умножении на выражение в скобках (например,(1 - Скидка/100)) убедитесь, что полеСкидкане содержит NULL. Иначе всё выражение вернёт NULL, а не 1, как можно было бы ожидать.
Работа с виртуальными таблицами и временными таблицами
При умножении данных из виртуальных таблиц (например, остатков или оборотов) учитывайте их особенности: некоторые поля могут быть не доступны для прямых вычислений. Типичный пример — умножение количества на цену в таблице остатков:
ВЫБРАТЬ
ОстаткиТоваров.Номенклатура КАК Товар,
ОстаткиТоваров.КоличествоОстатков * ОстаткиТоваров.Цена КАК СуммаОстатков
ИЗ
РегистрНакопления.ОстаткиТоваров.Остатки(&ДатаОтчета,) КАК ОстаткиТоваров
Для сложных вычислений удобно использовать временные таблицы:
// Создаём временную таблицу с промежуточными данными
ВЫБРАТЬ
Товары.Ссылка КАК Ссылка,
Товары.Цена * 1.2 КАК ЦенаСНДС
ПОМЕСТИТЬ ВТ_Цены
ИЗ
Справочник.Товары КАК Товары;
// Используем данные из временной таблицы
ВЫБРАТЬ
Остатки.Номенклатура КАК Товар,
Остатки.КоличествоОстатков * ВТ_Цены.ЦенаСНДС КАК Сумма
ИЗ
РегистрНакопления.ОстаткиТоваров.Остатки(&ДатаОтчета,) КАК Остатки
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Цены КАК ВТ_Цены
ПО Остатки.Номенклатура = ВТ_Цены.Ссылка
Убедиться, что оба операнда числовые|Проверить наличие NULL с помощью ЕСТЬNULL()|Учесть порядок операций при группировке|Протестировать запрос на небольшом наборе данных-->
Типичные ошибки и как их избежать
Даже опытные разработчики допускают ошибки при умножении в запросах. Рассмотрим наиболее распространённые:
| Ошибка | Причина | Решение |
|---|---|---|
| Результат умножения — NULL | Одно из полей содержит NULL | Использовать ЕСТЬNULL(Поле, 0) |
| Ошибка типов | Попытка умножить строку на число | Привести типы с помощью ВЫРАЗИТЬ() |
| Некорректная сумма при группировке | Умножение выполняется после агрегации | Использовать вложенные запросы или выносить умножение в подзапрос |
| Переполнение числового типа | Результат превышает максимальное значение типа | Явно указать тип с достаточной точностью: ЧИСЛО(15, 2) |
Особое внимание стоит уделить работе с NULL. Например, следующий запрос вернёт NULL для всех строк, где Скидка не заполнена:
ВЫБРАТЬ
Цена * (1 - Скидка/100) КАК ЦенаСоСкидкой
Правильный вариант:
ВЫБРАТЬ
Цена * (1 - ЕСТЬNULL(Скидка, 0)/100) КАК ЦенаСоСкидкой
Почему результат умножения может быть неточным?
В 1С:Предприятие числовые значения хранятся с ограниченной точностью. При умножении больших чисел или операциях с плавающей запятой возможны ошибки округления. Например, 1.1 * 3 может дать результат 3.3000000000000003 вместо ожидаемых 3.3. Для финансовых расчётов используйте тип ЧИСЛО(15, 2) и функцию ОКРУГЛ().)
Оптимизация запросов с умножением
Умножение в запросах может замедлять выполнение, особенно при работе с большими объёмами данных. Следующие рекомендации помогут оптимизировать производительность:
- ⚡ Выносите умножение в подзапросы, если оно не требуется на ранних этапах выполнения.
- 📈 Используйте индексированные поля в выражениях для умножения (например, предварительно рассчитанные поля в регистрах).
- 🔄 Избегайте умножения в циклах — лучше выполнить одно вычисление в запросе, чем пересчитывать значения для каждой строки в коде.
Пример оптимизированного запроса:
// Плохо: умножение выполняется для каждой записи
ВЫБРАТЬ
Товары.Наименование,
Товары.Цена Товары.Количество (1 + ЕСТЬNULL(Товары.НДС, 0)/100) КАК СуммаСНДС
ИЗ
Документ.РеализацияТоваров.Товары КАК Товары;
// Лучше: предварительно рассчитать коэффициент НДС
ВЫБРАТЬ
Товары.Наименование,
(Товары.Цена Товары.Количество) Коэффициенты.Коэффициент КАК СуммаСНДС
ИЗ
Документ.РеализацияТоваров.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ
(
ВЫБРАТЬ
1 КАК Коэффициент
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
1 + ЕСТЬNULL(Товары.НДС, 0)/100 КАК Коэффициент
ИЗ
Документ.РеализацияТоваров.Товары КАК Товары
) КАК Коэффициенты
⚠️ Внимание: При оптимизации запросов с умножением учитывайте, что некоторые преобразования (например, приведение типов) могут повлиять на план выполнения запроса. Всегда проверяйте производительность на реальных данных с помощью ПланЗапроса().
Практические примеры умножения в запросах
Рассмотрим несколько реальных сценариев, где требуется умножение в запросах:
1. Пересчёт цен в другую валюту
ВЫБРАТЬ
Товары.Наименование,
Товары.Цена * Курсы.Курс КАК ЦенаВДолларах
ИЗ
Справочник.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних(&Дата,) КАК Курсы
ПО Товары.ВалютаЦены = Курсы.Валюта
2. Расчёт процентов от суммы
ВЫБРАТЬ
Документы.Номер,
Документы.СуммаДокумента * (Документы.ПроцентАванса / 100) КАК СуммаАванса
ИЗ
Документ.ЗаказыПокупателей КАК Документы
3. Умножение с учётом нескольких условий
ВЫБРАТЬ
Товары.Наименование,
ВЫБОР
КОГДА Товары.Категория = &Категория1 И Товары.Сезонный = ИСТИНА
ТОГДА Товары.Цена 1.3 Товары.Количество
КОГДА Товары.Категория = &Категория2
ТОГДА Товары.Цена 0.8 Товары.Количество
ИНАЧЕ Товары.Цена * Товары.Количество
КОНЕЦ КАК Сумма
FAQ: Частые вопросы по умножению в запросах 1С
Как умножить поле на константу в запросе?
Используйте прямое умножение: ВЫБРАТЬ Поле * 1.2 КАК Результат. Для параметров запроса используйте конструкцию &Параметр:
ВЫБРАТЬ
Цена * &Коэффициент КАК НоваяЦена
Где &Коэффициент — параметр, передаваемый в запрос.
Почему при умножении двух чисел получаю ошибку "Типы не совместимы"?
Ошибка возникает, если одно из полей имеет нечисловой тип (например, строка или булево значение). Используйте ВЫРАЗИТЬ() для явного приведения:
ВЫБРАТЬ
ВЫРАЗИТЬ(Поле1 КАК ЧИСЛО(10, 2)) * ВЫРАЗИТЬ(Поле2 КАК ЧИСЛО(10, 2))
Можно ли умножать данные из разных таблиц в одном запросе?
Да, но для этого нужно использовать СОЕДИНЕНИЕ. Пример:
ВЫБРАТЬ
Заказы.Номер,
Заказы.Количество * Товары.Вес КАК ОбщийВес
ИЗ
Документ.ЗаказыПокупателей КАК Заказы
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Товары КАК Товары
ПО Заказы.Товар = Товары.Ссылка
Как округлить результат умножения?
Используйте функцию ОКРУГЛ():
ВЫБРАТЬ
ОКРУГЛ(Цена Количество 1.2, 2) КАК СуммаСНДС
Где 2 — количество знаков после запятой.
Что делать, если при умножении получаю переполнение?
Явно укажите тип данных с достаточной точностью:
ВЫБРАТЬ
ВЫРАЗИТЬ(БольшоеЧисло1 * БольшоеЧисло2 КАК ЧИСЛО(20, 0)) КАК Результат
Или разбейте вычисление на части:
ВЫБРАТЬ
(БольшоеЧисло1 / 1000) (БольшоеЧисло2 / 1000) 1000000 КАК Результат