Как работать с числами в языке запросов 1С: синтаксис и примеры
Содержание
Число в запросе 1С пишется прямо в тексте, без кавычек и с точкой в качестве разделителя дробной части: ГДЕ Остаток > 0, Цена * 1.2. Если значение меняется от запуска к запуску, его не вклеивают в текст, а передают параметром: ГДЕ Сумма >= &МинСумма плюс Запрос.УстановитьПараметр("МинСумма", 1000).
Типичная ситуация: программист пишет отбор «суммы больше полутора тысяч», ставит 1,5 или 1 500 — и получает синтаксическую ошибку. Или отчёт показывает пустые итоги, потому что в левом соединении пришёл NULL, а сравнение с ним молча возвращает «ложь». Ниже — синтаксис числовых констант и параметров в языке запросов платформы 1С:Предприятие 8.3, функции для математики и рабочие приёмы против NULL.
Как записать число-константу в тексте запроса
Числовой литерал в запросе — это просто цифры. Никаких кавычек, пробелов и знаков валюты.
✅ Правильно:
100— целое;0.18— дробное, разделитель — точка;-5— отрицательное, минус ставится перед числом;0— ноль, часто нужен как значение по умолчанию.
❌ Неправильно:
0,18— запятая в запросе разделяет поля и аргументы, парсер увидит два числа;1 500— пробел внутри числа не допускается;"100"— это уже строка, а не число;1e3— экспоненциальная запись язык запросов не понимает.
Константу можно использовать везде, где допустимо выражение: в списке полей, в условиях ГДЕ и ИМЕЮЩИЕ, в ВЫБОР, в арифметике.
ВЫБРАТЬ
Товары.Ссылка КАК Номенклатура,
Товары.Цена * 1.2 КАК ЦенаСНаценкой,
0 КАК Скидка
ИЗ
Справочник.Номенклатура КАК Товары
ГДЕ
Товары.Цена > 0
И Товары.ВесНетто МЕЖДУ 0.5 И 10
Константа в списке полей («0 КАК Скидка») — обычный приём для запросов с ОБЪЕДИНИТЬ ВСЕ. В одной части поле считается, в другой его нет — туда ставят ноль, чтобы колонки совпали по числу и типу.
ВЫБРАТЬ
Продажи.Номенклатура,
Продажи.СуммаОборот КАК Продажа,
0 КАК Возврат
ИЗ
РегистрНакопления.Продажи.Обороты КАК Продажи
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Возвраты.Номенклатура,
0,
Возвраты.Сумма
ИЗ
Документ.ВозвратТоваровОтПокупателя.Товары КАК Возвраты
Ставьте 0, а не NULL, если потом по этой колонке будет СУММА. С нулём итог считается привычно, с NULL придётся оборачивать результат в ЕСТЬNULL.
Список значений для условия В тоже пишется числами через запятую: ГДЕ Документ.КоличествоМест В (1, 2, 3). Здесь запятая — разделитель элементов, поэтому дробные значения внутри списка пишутся только через точку.
Числа в условиях ВЫБОР и группировках
Константы часто нужны, чтобы разложить суммы по «корзинам». Например, разбить дебиторку по размеру долга:
ВЫБРАТЬ
Долги.Контрагент,
Долги.СуммаОстаток,
ВЫБОР
КОГДА Долги.СуммаОстаток < 10000
ТОГДА 1
КОГДА Долги.СуммаОстаток < 100000
ТОГДА 2
ИНАЧЕ 3
КОНЕЦ КАК ГруппаДолга
ИЗ
ВременнаяТаблицаДолгов КАК Долги
Ветки КОГДА проверяются сверху вниз, первая подошедшая побеждает. Долг 9 500 попадёт в группу 1, долг 50 000 — в группу 2, долг 250 000 — в группу 3. Порядок условий здесь важен: если поставить < 100000 первым, в группу 1 не попадёт никто.
Если все ветки возвращают числа, колонка получится числовой, и по ней можно группировать и сортировать. Смешивать в ветках число и строку не стоит: колонка станет составного типа, и сортировка перестанет работать предсказуемо.
Пороги 10000 и 100000 в реальной обработке тоже лучше вынести в параметры &Порог1 и &Порог2, чтобы пользователь мог менять их без доработки.
Передача чисел параметром: когда и как
Если число задаёт пользователь, берётся из настроек или считается в коде, его передают параметром. Имя параметра начинается с амперсанда.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура,
| Остатки.КоличествоОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
|ГДЕ
| Остатки.КоличествоОстаток < &МинОстаток";
Запрос.УстановитьПараметр("МинОстаток", 10);
Результат = Запрос.Выполнить();
Почему параметр лучше склейки строк вида "... < " + Формат(МинОстаток, "ЧГ=0"):
- 🔒 нет проблем с форматом: платформа сама передаёт число как число, без разделителей групп и запятых;
- ⚡ текст запроса не меняется, СУБД может повторно использовать план выполнения;
- 🧹 код читается проще, а ошибки видны сразу.
Если всё-таки собираете текст запроса строкой, число превращайте через Формат(Число, "ЧРД=.; ЧГ=0"). Обычное Строка(1500.5) даст «1 500,5» с неразрывным пробелом и запятой — запрос упадёт.
Тип значения параметра
В параметр нужно передавать именно значение типа Число. Частая ловушка — число, прочитанное из поля ввода строкового типа или из файла: в параметр уходит строка "10". Сравнение числового поля со строкой не даёт ожидаемого результата, отбор возвращает пустую выборку.
Приведите значение в коде заранее:
МинОстаток = Число(СтрокаИзФайла);
Запрос.УстановитьПараметр("МинОстаток", МинОстаток);
Значение по умолчанию для необязательного параметра
Бывает, что порог задавать не всегда нужно. Чтобы не держать два текста запроса, передайте признак и само число:
ГДЕ
(НЕ &ОтбиратьПоСумме ИЛИ Т.Сумма >= &МинСумма)
Если ОтбиратьПоСумме = Ложь, условие пропускает все строки. Значение МинСумма всё равно нужно установить, например нулём, иначе платформа сообщит о незаданном параметре.
Один параметр в нескольких местах
Параметр можно использовать в тексте сколько угодно раз, значение устанавливается один раз. Удобно для порогов и коэффициентов:
ВЫБРАТЬ
Т.Номенклатура,
Т.Сумма * &Коэффициент КАК СуммаПересчет
ИЗ
ВременнаяТаблица КАК Т
ГДЕ
Т.Сумма * &Коэффициент > &Порог
Округление и арифметика в запросе 1С
Язык запросов поддерживает четыре действия: +, -, *, /. Скобки работают как в математике. Деление всегда дробное: 7 / 2 вернёт 3.5, а не 3.
ВЫРАЗИТЬ: приведение к длине и точности
Классический способ округлить число в запросе — привести его к типу с нужным числом знаков:
ВЫРАЗИТЬ(Т.Сумма / Т.Количество КАК ЧИСЛО(15, 2)) КАК Цена
Здесь 15 — общая длина числа, 2 — знаков после точки. Этот же приём обрезает «хвосты» вроде 33.333333333 после деления, которые потом портят группировку и сравнение.
Длину выбирайте с запасом. Если значение не помещается в ЧИСЛО(5, 2), то есть больше 999.99, запрос завершится ошибкой переполнения на стороне СУБД.
ОКР, ЦЕЛ и математические функции
В современных релизах платформы (начиная с 8.3.20) в язык запросов добавлены функции, которых раньше не было:
| Функция | Что делает | Пример |
|---|---|---|
ОКР(x, n) | округление до n знаков | ОКР(Т.Сумма * 0.13, 2) |
ЦЕЛ(x) | целая часть числа | ЦЕЛ(Т.Минуты / 60) |
POW(x, y) | возведение в степень | POW(1.01, 12) |
SQRT(x) | квадратный корень | SQRT(Т.Площадь) |
EXP, LOG, LOG10 | экспонента и логарифмы | LOG10(Т.Значение) |
SIN, COS, TAN и обратные | тригонометрия | редко нужны в учёте |
На более старой платформе этих функций нет, и запрос с ними не пройдёт проверку синтаксиса. Там округляют через ВЫРАЗИТЬ, а целую часть получают через приведение к ЧИСЛО(15, 0) с учётом округления или считают уже в коде после выборки.
Остаток от деления через ЦЕЛ считается так:
Т.Количество - ЦЕЛ(Т.Количество / Т.ВУпаковке) * Т.ВУпаковке КАК Россыпь
Пример: 47 штук, в упаковке 12. ЦЕЛ(47 / 12) = 3, 3 * 12 = 36, 47 - 36 = 11 штук россыпью.
Деление на ноль
Если знаменатель может оказаться нулём, обязательно защищайте выражение. Иначе на клиент-серверной базе запрос упадёт с ошибкой СУБД о делении на ноль.
ВЫБОР
КОГДА Т.Количество = 0
ТОГДА 0
ИНАЧЕ Т.Сумма / Т.Количество
КОНЕЦ КАК Цена
Числа и NULL: сравнение, суммы, соединения
NULL — это не ноль, а отсутствие значения. Он появляется в трёх типовых местах:
- 🔗 левое соединение не нашло пары — все поля правой таблицы равны NULL;
- 📭
СУММАпо пустому набору строк — результат NULL, а не 0; - 🧩 реквизит составного типа содержит значение другого типа.
Почему «= NULL» не работает
Любое сравнение с NULL через =, <>, >, < не даёт «истину». Условие ГДЕ Остатки.Количество = NULL не вернёт ни одной строки. Правильная проверка:
ГДЕ Остатки.КоличествоОстаток ЕСТЬ NULL
и обратная — НЕ Остатки.КоличествоОстаток ЕСТЬ NULL.
ЕСТЬNULL для подстановки нуля
Арифметика с NULL тоже даёт NULL: 100 + NULL = NULL. Поэтому поля из присоединённой таблицы оборачивают в ЕСТЬNULL:
ВЫБРАТЬ
Номенклатура.Ссылка,
ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток,
ЕСТЬNULL(Остатки.КоличествоОстаток, 0) * Номенклатура.Цена КАК СуммаОстатка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ПО Номенклатура.Ссылка = Остатки.Номенклатура
Без ЕСТЬNULL товары без остатка выпадут из условия ГДЕ Остаток < 5 — хотя по смыслу это как раз нулевой остаток, и он меньше пяти.
Составной тип и числа
Если реквизит может хранить и число, и, например, строку, перед арифметикой отберите только числовые значения:
ГДЕ ТИПЗНАЧЕНИЯ(Т.Значение) = ТИП(ЧИСЛО)
а в списке полей приведите тип явно: ВЫРАЗИТЬ(Т.Значение КАК ЧИСЛО(15, 2)).
Преобразовать строку в число средствами самого языка запросов нельзя. Если номер или сумма хранится строкой, выберите строку как есть и переведите её через Число() в коде, обработав исключение для нецифровых значений.
Как числовые условия влияют на скорость запроса
Числа в запросах редко тормозят сами по себе. Тормозят выражения, которые мешают СУБД использовать индекс.
🐢 Медленно:
ГДЕ Т.Сумма * 1.2 > 10000
ГДЕ ВЫРАЗИТЬ(Т.Сумма КАК ЧИСЛО(15, 0)) = 500
ГДЕ ЕСТЬNULL(Т.Количество, 0) > 0
⚡ Быстрее:
ГДЕ Т.Сумма > &Порог // Порог = 10000 / 1.2, посчитан в коде
ГДЕ Т.Сумма >= 499.5 И Т.Сумма < 500.5
ГДЕ Т.Количество > 0 // NULL и так не пройдёт сравнение
Правило простое: поле в условии должно стоять «голым», а вся математика — на стороне константы или параметра. Тогда СУБД сравнивает значения прямо по индексу, если он есть.
Ещё несколько приёмов:
- Считайте суммы и количества агрегатными функциями в запросе (
СУММА,МАКСИМУМ,КОЛИЧЕСТВО), а не перебором выборки в цикле. - Для виртуальных таблиц регистров числовые и прочие отборы ставьте в параметры самой таблицы, а не в
ГДЕпосле неё. - Не используйте
ВЫРАЗИТЬдля промежуточных вычислений — приводите тип один раз, в итоговом поле. - Длинные списки констант в
В (1, 2, 3, …)заменяйте параметром-массивом:В (&СписокКодов).
Частые ошибки с числами в запросах и их причины
0,18) или пробел (1 500). Замените на 0.18 и 1500, а лучше передайте значение параметром.УстановитьПараметр и оберните поле в ЕСТЬNULL.СУММА по присоединённой таблице без пар даёт NULL. Используйте ЕСТЬNULL(СУММА(Поле), 0).УстановитьПараметр не совпадает с именем в тексте: опечатка, лишний пробел, другая раскладка буквы. Скопируйте имя из текста запроса без амперсанда. Регистр букв роли не играет.ВЫРАЗИТЬ приводит значение к слишком короткому типу. Увеличьте длину, например до ЧИСЛО(15, 2) или ЧИСЛО(20, 4).ВЫБОР КОГДА … = 0 ТОГДА 0 ИНАЧЕ … КОНЕЦ.ВЫРАЗИТЬ или обновите платформу и режим совместимости по согласованию с ответственным за базу.Режим совместимости меняют в Конфигураторе, и после этого конфигурацию придётся обновить. Делайте это только на копии базы или после резервного копирования, с согласия того, кто отвечает за доработки.
Частые вопросы
Какой тип у константы 0 в результате запроса?
Число без заданной длины и точности. Если важно, чтобы колонка имела конкретный формат, приведите её: ВЫРАЗИТЬ(0 КАК ЧИСЛО(15, 2)).Как проверить запрос с числовыми параметрами без написания кода?
Можно ли передать в один параметр список чисел?
Поле В (&Список). Платформа подставит все элементы сама.Чем ОКР отличается от ВЫРАЗИТЬ КАК ЧИСЛО?
ОКР только округляет и не меняет описание типа. ВЫРАЗИТЬ задаёт длину и точность поля, поэтому может вызвать переполнение, если значение не помещается.