При работе с языком запросов 1С программисты часто сталкиваются с необходимостью создания вычисляемых полей. Типичный пример — расчет цены на основании суммы и количества. Однако простая, на первый взгляд, арифметическая операция может привести к ошибке «Неверные параметры "/"». В этой статье мы подробно разберем, почему возникает эта проблема, как ее диагностировать и какие существуют лучшие практики для создания надежных вычисляемых полей в запросах и отчетах.
Проанализируем ситуацию, с которой столкнулся автор темы. В его запросе выполнялось деление Рег.Сумма / Рег.Количество. Система выдала ошибку, так как один из операндов (или оба) не являлся числом. В ходе обсуждения выяснилось, что ресурсы регистра сведений были ошибочно заданы как Строка вместо Число.
Для платформы 1С операция деления определена только для числовых типов данных. Если в конфигураторе для ресурса или реквизита установлен тип «Строка», «Дата» или «СправочникСсылка», попытка деления вызовет исключение еще на этапе компиляции запроса или получения информации о наборе данных.
Рассмотрим, как проверить тип данных в реальном времени. Если вы не уверены, какой тип возвращает поле, можно использовать функцию ТИПЗНАЧЕНИЯ в консоли запросов:
ВЫБРАТЬ
ТИПЗНАЧЕНИЯ(Рег.Сумма) КАК ТипСуммы,
ТИПЗНАЧЕНИЯ(Рег.Количество) КАК ТипКоличества
ИЗ
РегистрСведений.ЦеныПоступления.СрезПоследних() КАК Рег
Если результат функции покажет, что это не число, проблему нужно решать в метаданных конфигурации, изменив тип поля на Число с нужной точностью.
Еще одна тривиальная, но часто встречающаяся ошибка — пропуск запятой перед вычисляемым полем. В языке запросов 1С, если между двумя полями нет запятой, второе поле воспринимается как псевдоним (алиас) для первого. Рассмотрим некорректный пример:
ВЫБРАТЬ
Рег.НоменклатураАртикул
Рег.Сумма / Рег.Количество КАК Цена
ИЗ
Рег КАК Рег
В данном случае система решит, что Рег.Сумма — это попытка назначить имя полю Артикул, а символ / окажется синтаксически неуместным в этой позиции. Всегда внимательно проверяйте наличие запятых при перечислении полей в секции ВЫБРАТЬ.
Даже если типы данных верны, запрос может упасть в процессе выполнения (Runtime error), если значение в поле Количество окажется равным нулю. В отличие от некоторых СУБД, 1С требует явной обработки таких ситуаций. Разберем, как сделать запрос безопасным с помощью конструкции ВЫБОР:
ВЫБРАТЬ
Рег.Номенклатура,
ВЫБОР
КОГДА Рег.Количество = 0 ТОГДА 0
ИНАЧЕ Рег.Сумма / Рег.Количество
КОНЕЦ КАК Цена
ИЗ
Рег КАК Рег
Этот подход гарантирует, что ваша программа не «вылетит» при наличии пустых остатков или ошибочных данных в регистре.
Когда мы работаем с виртуальными таблицами (например, СрезПоследних) или используем ЛЕВОЕ СОЕДИНЕНИЕ, в полях могут появиться значения NULL. Операция деления с участием NULL всегда возвращает NULL. Хотя это не вызывает ошибку «Неверные параметры», это может привести к пустым ячейкам в отчете. Проанализируем, как использовать функцию ЕСТЬNULL для подстановки значений по умолчанию:
ВЫБРАТЬ
ВЫБОР
КОГДА ЕСТЬNULL(Рег.Количество, 0) = 0 ТОГДА 0
ИНАЧЕ ЕСТЬNULL(Рег.Сумма, 0) / Рег.Количество
КОНЕЦ КАК Цена
ИЗ
РегистрСведений.Цены.СрезПоследних(&Дата) КАК Рег
Если поле имеет составной тип или тип «ЛюбаяСсылка», 1С может затрудняться с определением типа на этапе проверки запроса. В таких случаях мы используем функцию ВЫРАЗИТЬ. Она не только помогает избежать ошибок типизации, но и позволяет ограничить разрядность числа, что важно для точности вычислений.
ВЫБРАТЬ
ВЫРАЗИТЬ(Рег.Сумма КАК ЧИСЛО(15, 2)) / ВЫРАЗИТЬ(Рег.Количество КАК ЧИСЛО(15, 3)) КАК Цена
ИЗ
Рег КАК Рег
Важно: Помните, что ВЫРАЗИТЬ не может превратить строку в число, если это поле в конфигураторе жестко определено как строковое. Эта функция работает только для уточнения уже совместимых типов или для приведения составных типов к конкретному.
Если вы разрабатываете отчет на СКД, вычислять цену прямо в тексте запроса — не всегда лучшая идея. Проблема заключается в расчете итогов. Если в запросе вы просто поделите сумму на количество, то в строке «Итого» СКД попытается сложить все цены, что математически бессмысленно.
Правильнее будет вынести расчет на вкладку «Ресурсы» в схеме компоновки. Для поля Цена укажите следующее выражение:
Сумма(Сумма) / Сумма(Количество)
В этом случае СКД сначала просуммирует все суммы и все количества по группировке, а затем выполнит деление. Это даст корректную средневзвешенную цену для любого уровня итогов. Также не забудьте добавить проверку на ноль в выражении ресурса:
ВЫБОР КОГДА Сумма(Количество) = 0 ТОГДА 0 ИНАЧЕ Сумма(Сумма) / Сумма(Количество) КОНЕЦ
Для успешного создания вычисляемых полей в запросах 1С придерживайтесь следующих правил:
Число.ВЫБОР КОГДА ... ТОГДА.ЕСТЬNULL для входящих данных, особенно при левых соединениях.Применяя эти методы, вы сможете создавать стабильные и производительные запросы, избегая стандартных ошибок платформы.