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

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

Как работать с числами в запросе 1С

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

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

Основные задачи, которые решает разработчик: записать числовой литерал прямо в тексте запроса, передать число через параметр, привести строку или значение составного типа к числу с помощью конструкции ВЫРАЗИТЬ, выполнить арифметику без потери точности и корректно сравнить числа в условии ГДЕ. Каждая из этих задач имеет подводные камни.

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

Числовые литералы в тексте запроса

Самый простой способ указать число — написать литерал прямо в тексте запроса. Числа записываются без кавычек, дробная часть отделяется точкой, а не запятой. Запятая в этом контексте будет воспринята как разделитель элементов списка и вызовет синтаксическую ошибку.

ВЫБРАТЬ

Товары.Номенклатура,

Товары.Количество

ИЗ

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

ГДЕ

Товары.Количество > 10

И Товары.Цена >= 1500.50

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

Литералы удобны для константных порогов, но встраивать «магические числа» в текст запроса — плохая практика: при изменении порога придётся менять код. Для значений, которые могут меняться или приходят извне, используйте параметры.

Передача числа через параметр запроса

Параметр — правильный способ передать число из кода в запрос. Имя параметра начинается с символа амперсанда, значение устанавливается методом УстановитьПараметр до выполнения запроса.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Заказы.Ссылка,

| Заказы.СуммаДокумента

|ИЗ

| Документ.ЗаказКлиента КАК Заказы

|ГДЕ

| Заказы.СуммаДокумента > &МинимальнаяСумма";

Запрос.УстановитьПараметр("МинимальнаяСумма", 100000);

Результат = Запрос.Выполнить();

Тип параметра определяется типом переданного значения. Если передать целое число, а сравниваемое поле имеет дробную часть, сравнение всё равно выполнится корректно — платформа сопоставит числовые типы. Проблемы возникают, когда типы принципиально несовместимы, например параметр-строка сравнивается с числовым полем: в этом случае сравнение вернёт ложь или запрос не выполнится в зависимости от СУБД.

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

Приведение к числу через ВЫРАЗИТЬ

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

ВЫБРАТЬ

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

ИЗ

РегистрСведений.ЗначенияСвойств КАК Данные

Типичный сценарий — значение хранится в составном типе или в ресурсе с избыточной разрядностью, а для сравнения или соединения нужен строго определённый формат. Например, соединение двух таблиц по числовому полю с разной разрядностью может не найти совпадений из-за различий в хранимом представлении, и приведение обеих сторон к ЧИСЛО(15,2) решает проблему.

Ограничения и поведение при переполнении

Если значение не помещается в указанную длину, результат приведения будет NULL, а не ошибкой выполнения. Это коварно: запрос отработает, но строки «потеряются». Поэтому разрядность выбирайте с запасом, а результат проверяйте на появление NULL там, где их не ожидали.

При приведении строки к числу срабатывает только если строка содержит корректное числовое представление без лишних символов, пробелов и букв. Иначе результат — NULL. Для «грязных» данных приведение в запросе ненадёжно: строку лучше предварительно очистить в коде на встроенном языке.

Типичные ошибки
01
ВЫРАЗИТЬ(Поле КАК ЧИСЛО(10,2)) для сумм, которые могут превышать 8 разрядов до запятой — лишние значения превращаются в NULL без сообщения об ошибке
02
Приведение строки с пробелами или неразрывными пробелами к числу — результат NULL, строки пропадают из выборки
03
Сравнение числа со строкой без приведения типов — сравнение всегда ложно или запрос падает на некоторых СУБД

Арифметика и округление в запросе

В запросе доступны стандартные операции: сложение, вычитание, умножение, деление, а также вычисление остатка через оператор % (в поддерживаемых СУБД). Приоритет операций стандартный, скобки работают как обычно.

ВЫБРАТЬ

Строки.Количество * Строки.Цена КАК Сумма,

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

ИЗ

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

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

При делении всегда учитывайте делитель, равный нулю. Деление на ноль в запросе приводит к ошибке выполнения. Защититесь конструкцией ВЫБОР: если делитель равен 0, вернуть 0 или NULL, иначе выполнить деление.

bsl
ВЫБОР КОГДА Данные.Количество = 0 ТОГДА 0 ИНАЧЕ ВЫРАЗИТЬ(Данные.Сумма / Данные.Количество КАК ЧИСЛО(15, 2)) КОНЕЦ КАК СредняяЦена

Сравнение чисел и ловушки точности

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

Любое сравнение с NULL даёт не ИСТИНА и не ЛОЖЬ, а неопределённый результат, и строка не попадает в выборку. Если поле может быть NULL (например, после левого соединения), оборачивайте его в ЕСТЬNULL(Поле, 0) перед сравнением.

Вычисленные дробные значения могут отличаться в последних разрядах из-за особенностей представления чисел на СУБД. Сравнение на строгое равенство таких значений ненадёжно. Практический приём — сравнивать модуль разности с малым порогом или приводить обе стороны к одинаковой разрядности через ВЫРАЗИТЬ.

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

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

Количество строк в выборке
Норма

Совпадает с ожидаемым по контрольным данным

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

Строк меньше — вероятно, NULL в сравнении или переполнение при ВЫРАЗИТЬ

Значения вычисляемого поля
Норма

Дробная часть соответствует заданной точности

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

Дробная часть обрезана до целого — не задана разрядность

Поля после приведения типа
Норма

Нет неожиданных NULL

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

Появились NULL — значение не поместилось в длину или строка нечисловая

Числа в агрегатных функциях и итогах

Агрегатные функции СУММА, СРЕДНЕЕ, МИНИМУМ, МАКСИМУМ и КОЛИЧЕСТВО работают с числовыми полями напрямую. СРЕДНЕЕ возвращает дробный результат даже для целых исходных значений, поэтому его почти всегда стоит приводить к нужной разрядности.

ВЫБРАТЬ

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

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

ВЫРАЗИТЬ(СРЕДНЕЕ(Продажи.Цена) КАК ЧИСЛО(15, 2)) КАК СредняяЦена

ИЗ

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

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

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

Учтите, что СУММА по полю, содержащему NULL, игнорирует такие строки, а КОЛИЧЕСТВО(Поле) не считает NULL-значения, в отличие от КОЛИЧЕСТВО(*). Если итог не сходится с ожиданием, первым делом проверьте наличие NULL в группируемых данных.

Выбор подхода: литерал, параметр или приведение

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

Маршрут решения

Как выбрать действие

Порог фиксирован и не меняется логикой программы (например, проверка > 0)Используйте числовой литерал прямо в тексте запроса
Значение приходит из формы, отбора или алгоритмаПередавайте число параметром через УстановитьПараметр
Поля соединяются или сравниваются, но имеют разную разрядность или составной типПриведите обе стороны к ЧИСЛО(длина, точность) через ВЫРАЗИТЬ
Строка содержит число с посторонними символамиОчищайте строку в коде до запроса, приведение в запросе даст NULL

Перед переносом запроса в рабочую базу проверьте его на копии с реальными объёмами данных: переполнение разрядности и NULL-эффекты часто проявляются только на больших выборках. Консоль запросов позволяет быстро прогнать варианты и сравнить количество строк и значения вычисляемых полей.

Итог

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

Число в запросе 1С задаётся литералом с точкой, параметром или приведением ВЫРАЗИТЬ к ЧИСЛО(длина, точность). Главные риски — NULL при переполнении разрядности, сравнение несовместимых типов и деление на ноль. Проверяйте результат на количество строк и неожиданные NULL.

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

Как задать отрицательное число в запросе 1С?

Напишите литерал со знаком минус: ГДЕ Остаток < -10. Для параметра передайте отрицательное значение из кода — платформа корректно обработает знак. Унарный минус работает и в выражениях: -Поле * 2.

Почему ВЫРАЗИТЬ к ЧИСЛО возвращает NULL?

Две основные причины: значение не помещается в указанную длину (например, сумма с десятью разрядами приводится к ЧИСЛО(8,2)) или приводится строка, содержащая нечисловые символы, пробелы либо пустое значение. Увеличьте длину или предварительно очистите данные.

Как округлить число до целого в запросе?

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

Можно ли сравнивать число со строкой в условии ГДЕ?

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

Что делать, если при делении возникает ошибка деления на ноль?

Оберните выражение в конструкцию ВЫБОР: при делителе, равном нулю, возвращайте 0 или NULL, иначе выполняйте деление. Это стандартная защита, которую стоит применять всегда, когда делитель вычисляется из данных.

Чем отличается КОЛИЧЕСТВО(Поле) от КОЛИЧЕСТВО()?

КОЛИЧЕСТВО(Поле) считает только строки, где поле не равно NULL, а КОЛИЧЕСТВО() считает все строки группы. Если итог по полю меньше ожидаемого, проверьте данные на NULL-значения.