При получении цен или суммовых показателей в запросе 1С разработчики нередко сталкиваются с ситуацией, когда число с дробной частью (например, 30.44) возвращается или отображается как целое (30). Разберем причины нежелательного округления, особенности определения разрядности числовых полей платформой, а также научимся правильно применять функцию ВЫРАЗИТЬ и устранять сопутствующие ошибки группировки.
Сам по себе язык запросов 1С не усекает дробную часть данных без явных инструкций. Если значение срезается, проанализируем основные причины:
ВЫБОР ... КОНЕЦ: Если внутри ветвей ТОГДА или ИНАЧЕ возвращаются значения с разной точностью (например, целочисленный литерал 0 или реквизит с нулевой точностью), СУБД может автоматически определить тип результирующей колонки как целое число с разрядностью (X, 0). В результате все дробные части значений будут отсечены.Сообщить() или выводе в поля табличного документа число неявно преобразуется в строку. Если формат ячейки или поля формы настроен без дробных цифр (ЧДЦ=0), значение будет выглядеть как целое число, хотя в памяти содержит копейки.Число(10, 0), дробная часть автоматически отбрасывается при присвоении.Для гарантированного сохранения точности числового поля не требуется оборачивать каждый результат внутри условий КОГДА ... ТОГДА. Достаточно обернуть всю конструкцию ВЫБОР ... КОНЕЦ целиком в функцию ВЫРАЗИТЬ с указанием нужной длины и точности.
Посмотрим на пример правильного приведения типов для сложной конструкции расчета цены:
ВЫБРАТЬ
СпрНоменклатура.Ссылка КАК Номенклатура,
ВЫРАЗИТЬ(
ВЫБОР
КОГДА ЕСТЬNULL(ЦеныСрез.Цена, 0) <> 0
И (ЕСТЬNULL(ЦеныСрез.Цена, 0) < ЕСТЬNULL(ЦеныКонтрагентов.МинимальнаяЦена, 0)
ИЛИ ЕСТЬNULL(ЦеныКонтрагентов.МинимальнаяЦена, 0) = 0)
ТОГДА ЦеныСрез.Цена
КОГДА ЕСТЬNULL(ЦеныКонтрагентов.МинимальнаяЦена, 0) <> 0
ТОГДА ЦеныКонтрагентов.МинимальнаяЦена
ИНАЧЕ 0
КОНЕЦ КАК ЧИСЛО(15, 2)
) КАК ИтоговаяЦена
ИЗ
Справочник.Номенклатура КАК СпрНоменклатура
Важный момент: Оборачивание всей конструкции ВЫБОР в ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 2)) жестко фиксирует структуру и разрядность колонки в результирующей таблице СУБД, исключая двусмысленное определение типа.
При объединении функций приведения типов и секции СГРУППИРОВАТЬ ПО часто возникает ошибка вида «Поле не входит в группу...». Выясним причину этой ошибки:
Если в секции СГРУППИРОВАТЬ ПО выражение задано как ВЫРАЗИТЬ(Таблица.Поле КАК ЧИСЛО(10, 2)), то внутри секции ВЫБРАТЬ и в условиях КОГДА обращение к простому полю Таблица.Поле без агрегатных функций (МИНИМУМ, МАКСИМУМ, СУММА) будет отвергнуто компилятором запроса.
Разберем по шагам, как избежать этой проблемы:
МИНИМУМ() или МАКСИМУМ().Чтобы убедиться, что запрос возвращает правильные данные без искажения механизмами отображения, выполним следующие действия:
ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
ТаблицаРезультата через окно «Вычислить выражение» (Shift+F9). Это позволит увидеть реальные значения в ячейках без влияния форматирования пользовательского интерфейса.Число с допустимой длиной и точностью 2.