Почему в ячейке запроса вместо нуля отображается пустота и как это исправить?

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

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

Выясним причину: физическое значение и визуальное представление

Проанализируем ситуацию, с которой столкнулся разработчик: в запросе рассчитывается процентная разница между первой и последней ценой номенклатуры. Когда цены равны, формула возвращает ноль, но консоль запросов выводит пустоту.

Главное, что необходимо понимать: дело не в запросе. Запрос возвращает честное числовое значение 0. Проблема заключается исключительно в механизмах визуализации платформы «1С:Предприятие»:

  1. Поведение табличных элементов по умолчанию: в платформе 1С для ячеек таблиц (табличных частей, динамически сформированных таблиц значений на управляемой форме) по умолчанию активировано скрытие нулевых значений числового типа. Платформа визуально очищает нули для разгрузки интерфейса от лишней информации.
  2. Динамическая генерация колонок: большинство внешних консолей запросов создают колонки дерева или таблицы результата программно во время выполнения запроса. Если автор консоли не задал формат для генерируемого поля формы, применяется платформенное форматирование по умолчанию, скрывающее ноль.
  3. Проверка реального значения: чтобы убедиться, что в ячейке действительно число 0, достаточно дважды кликнуть на неё в консоли запросов или перейти в режим редактирования ячейки — платформа сразу отобразит фактическое числовое значение.

Ошибочный путь: использование конструкции «ВЫБОР ... ТОГДА "0"»

Иногда возникает соблазн принудительно вернуть символ нуля прямо в тексте запроса, написав следующую конструкцию:


ВЫБОР
    КОГДА РазницаПроцент = 0 ТОГДА "0"
    ИНАЧЕ РазницаПроцент
КОНЕЦ

Разберем, почему применять такой подход категорически не рекомендуется:

  1. Превращение колонки в составной тип: возвращая строку "0" в одном условии и число в ветке ИНАЧЕ, мы делаем колонку составного типа (Число, Строка).
  2. Нарушение сортировки: платформа упорядочивает составные типы раздельно — сначала группируются числа, затем строки (или наоборот, в зависимости от СУБД). В результате упорядочивание по полю перестанет работать корректно: строковый ноль не встанет между отрицательными и положительными числами.
  3. Невозможность агрегации и вычислений: к полю со строковым типом нельзя применить агрегатные функции (например, СУММА) или использовать его во временных таблицах для дальнейших математических расчетов.

Правильные способы вывода нуля

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

  1. Использование параметра форматной строки ЧН=0: в 1С за явный вывод нулевого значения отвечает параметр форматной строки ЧН=0. Если результат запроса выводится в отчет, макет или форму документа, достаточно задать формат ячейки или поля ввода:
    
    // В кодовой обработке формы:
    Элементы.ТаблицаРазницаПроцент.Формат = "ЧДЦ=2; ЧН=0";
    
    Параметр ЧН=0 указывает платформе принудительно отображать символ «0», если числовое значение равно нулю. Это сохраняет исходный тип данных Число и оставляет сортировку корректной.
  2. Настройка в схеме компоновки данных (СКД): если отчет строится на базе СКД, на вкладке «Наборы данных» выберите нужное поле, перейдите в колонку «Оформление» и в параметре «Формат» укажите ЧН=0. В СКД ноль гарантированно отобразится во всех таблицах и диаграммах.
  3. Выгрузка в табличный документ: если вы работаете в консоли запросов и вам необходимо продемонстрировать результат с нулями без изменения конфигурации, воспользуйтесь функцией выгрузки результата в табличный документ. В открывшемся табличном документе выделите числовую колонку, откройте свойства ячеек и укажите формат отображения нуля.

Скрытые ошибки в исходном запросе

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


ВЫБРАТЬ
    ЦеныСрезПервых.Номенклатура КАК Номенклатура,
    ЦеныСрезПервых.Цена КАК ПерваяЦена,
    ЦеныСрезПоследних.Цена КАК ПоследняяЦена,
    ВЫРАЗИТЬ(-((ЦеныСрезПервых.Цена - ЦеныСрезПоследних.Цена) / (ЦеныСрезПервых.Цена + ЦеныСрезПоследних.Цена) / 2) * 100 КАК ЧИСЛО(3, 0)) КАК РазницаПроцент
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПервых(&Начало, ВидЦены = &ВидЦены) КАК ЦеныСрезПервых
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Конец, ВидЦены = &ВидЦены) КАК ЦеныСрезПоследних
        ПО (ЦеныСрезПервых.Номенклатура = ЦеныСрезПоследних.Номенклатура)
СГРУППИРОВАТЬ ПО
    ЦеныСрезПервых.Номенклатура,
    ЦеныСрезПервых.Цена,
    ЦеныСрезПоследних.Цена
УПОРЯДОЧИТЬ ПО
    РазницаПроцент

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

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

Скорректированный и безопасный вариант вычисления разницы в запросе выглядит следующим образом:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    ЦеныСрезПервых.Номенклатура КАК Номенклатура,
    ЦеныСрезПервых.Цена КАК ПерваяЦена,
    ЕСТЬNULL(ЦеныСрезПоследних.Цена, 0) КАК ПоследняяЦена,
    ВЫБОР
        КОГДА (ЦеныСрезПервых.Цена + ЕСТЬNULL(ЦеныСрезПоследних.Цена, 0)) = 0 ТОГДА 0
        ИНАЧЕ ВЫРАЗИТЬ(-((ЦеныСрезПервых.Цена - ЕСТЬNULL(ЦеныСрезПоследних.Цена, 0)) / ((ЦеныСрезПервых.Цена + ЕСТЬNULL(ЦеныСрезПоследних.Цена, 0)) / 2)) * 100 КАК ЧИСЛО(3, 0))
    КОНЕЦ КАК РазницаПроцент
ИЗ
    РегистрСведений.ЦеныНоменклатуры.СрезПервых(&Начало, ВидЦены = &ВидЦены) КАК ЦеныСрезПервых
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Конец, ВидЦены = &ВидЦены) КАК ЦеныСрезПоследних
        ПО ЦеныСрезПервых.Номенклатура = ЦеныСрезПоследних.Номенклатура
УПОРЯДОЧИТЬ ПО
    РазницаПроцент

В результате запрос возвращает корректное число 0, защищен от деления на ноль и потери данных при соединениях, а для вывода цифры на экран в отчете или интерфейсе применяется стандартный формат ЧН=0.

← На главную