Почему в запросе 1С число округляется до целого и как настроить точность?

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

При получении цен или суммовых показателей в запросе 1С разработчики нередко сталкиваются с ситуацией, когда число с дробной частью (например, 30.44) возвращается или отображается как целое (30). Разберем причины нежелательного округления, особенности определения разрядности числовых полей платформой, а также научимся правильно применять функцию ВЫРАЗИТЬ и устранять сопутствующие ошибки группировки.

1. Почему происходит потеря точности и неявное округление

Сам по себе язык запросов 1С не усекает дробную часть данных без явных инструкций. Если значение срезается, проанализируем основные причины:

  1. Вывод типа результата в конструкции ВЫБОР ... КОНЕЦ: Если внутри ветвей ТОГДА или ИНАЧЕ возвращаются значения с разной точностью (например, целочисленный литерал 0 или реквизит с нулевой точностью), СУБД может автоматически определить тип результирующей колонки как целое число с разрядностью (X, 0). В результате все дробные части значений будут отсечены.
  2. Особенности отображения и преобразования в строку: При использовании метода Сообщить() или выводе в поля табличного документа число неявно преобразуется в строку. Если формат ячейки или поля формы настроен без дробных цифр (ЧДЦ=0), значение будет выглядеть как целое число, хотя в памяти содержит копейки.
  3. Разрядность реквизитов-приемников: Если результат запроса помещается в реквизит объекта или колонку таблицы значений с типом Число(10, 0), дробная часть автоматически отбрасывается при присвоении.

2. Корректное использование функции ВЫРАЗИТЬ для конструкции ВЫБОР

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

Посмотрим на пример правильного приведения типов для сложной конструкции расчета цены:


ВЫБРАТЬ
    СпрНоменклатура.Ссылка КАК Номенклатура,
    ВЫРАЗИТЬ(
        ВЫБОР
            КОГДА ЕСТЬNULL(ЦеныСрез.Цена, 0) <> 0 
                И (ЕСТЬNULL(ЦеныСрез.Цена, 0) < ЕСТЬNULL(ЦеныКонтрагентов.МинимальнаяЦена, 0) 
                   ИЛИ ЕСТЬNULL(ЦеныКонтрагентов.МинимальнаяЦена, 0) = 0)
                ТОГДА ЦеныСрез.Цена
            КОГДА ЕСТЬNULL(ЦеныКонтрагентов.МинимальнаяЦена, 0) <> 0
                ТОГДА ЦеныКонтрагентов.МинимальнаяЦена
            ИНАЧЕ 0
        КОНЕЦ КАК ЧИСЛО(15, 2)
    ) КАК ИтоговаяЦена
ИЗ
    Справочник.Номенклатура КАК СпрНоменклатура

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

3. Ошибка «Поле не входит в группу» при группировке

При объединении функций приведения типов и секции СГРУППИРОВАТЬ ПО часто возникает ошибка вида «Поле не входит в группу...». Выясним причину этой ошибки:

Если в секции СГРУППИРОВАТЬ ПО выражение задано как ВЫРАЗИТЬ(Таблица.Поле КАК ЧИСЛО(10, 2)), то внутри секции ВЫБРАТЬ и в условиях КОГДА обращение к простому полю Таблица.Поле без агрегатных функций (МИНИМУМ, МАКСИМУМ, СУММА) будет отвергнуто компилятором запроса.

Разберем по шагам, как избежать этой проблемы:

  1. Использовать агрегатные функции: Для числовых полей цен и сумм в группировках используйте функции МИНИМУМ() или МАКСИМУМ().
  2. Выносить выборку во временные таблицы: Оптимальный подход при работе с ценами — получить срез цен и остатки в отдельных пакетах запроса во временные таблицы, где для каждого товара будет гарантированно одна строка, после чего соединить их без использования тяжелых конструкций группировки по составным выражениям.

4. Проверка значений при отладке

Чтобы убедиться, что запрос возвращает правильные данные без искажения механизмами отображения, выполним следующие действия:

  1. Выгрузим результат запроса в таблицу значений: ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
  2. В точке останова откроем ТаблицаРезультата через окно «Вычислить выражение» (Shift+F9). Это позволит увидеть реальные значения в ячейках без влияния форматирования пользовательского интерфейса.
  3. Проверим типы колонок полученной таблицы: у нужной колонки должен быть тип Число с допустимой длиной и точностью 2.
← На главную