Как сложить булевы значения или преобразовать их в число в запросе 1С?

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

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

Разберем причины возникновения этой ошибки, а также рассмотрим правильные способы решения задачи как для арифметического сложения (подсчета количества), так и для логического объединения условий.

Почему не работает функция ВЫРАЗИТЬ для типа Булево

Проанализируем типичную ошибку: попытку выполнить конструкцию ВЫРАЗИТЬ(Таблица.ПолеБулево КАК Число(1)). В отличие от стандартного SQL-оператора CAST, функция ВЫРАЗИТЬ в языке запросов 1С имеет строго ограниченное назначение:

  1. Уточнение длины или точности примитивных типов: ограничение длины неограниченных строк Строка(100) или задание разрядности чисел.
  2. Приведение составных ссылочных типов: указание конкретного ссылочного типа конфигурации (например, ВЫРАЗИТЬ(Документ.Регистратор КАК Документ.РеализацияТоваровУслуг)) для обращения к реквизитам через точку без разыменования всей таблицы.

Функция ВЫРАЗИТЬ принципиально не выполняет конвертацию одного базового типа данных в другой (например, из Булево в Число или из Строка в Число). Для таких преобразований в языке запросов 1С применяется условная конструкция ВЫБОР.

Способ 1. Арифметическое сложение булевых полей (получение суммы)

Если необходимо получить числовую сумму (например, посчитать, сколько услуг из нескольких заказано: 0, 1, 2 и более), преобразуем каждое булево значение в 1 или 0 с помощью конструкции ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ.

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


ВЫБРАТЬ
    допусл.Ссылка КАК Ссылка,
    (ВЫБОР
        КОГДА допусл.ГрупповойТрансфер
            ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ + ВЫБОР
        КОГДА допусл.ИндивидуальныйТрансфер
            ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ) КАК ВсегоТрансферов
ИЗ
    допусл КАК допусл

Если требуется применить группировку и агрегацию к результату, обернем конструкцию в функцию СУММА или МАКСИМУМ:


ВЫБРАТЬ
    допусл.Ссылка КАК Ссылка,
    МАКСИМУМ(
        ВЫБОР
            КОГДА допусл.Перелет
                ТОГДА 1
            ИНАЧЕ 0
        КОНЕЦ +
        ВЫБОР
            КОГДА допусл.СтраховкаМедицинская
                ТОГДА 1
            ИНАЧЕ 0
        КОНЕЦ
    ) КАК КоличествоУслуг
ИЗ
    допусл КАК допусл
СГРУППИРОВАТЬ ПО
    допусл.Ссылка

Способ 2. Логическое сложение (получение единого флага Истина/Ложь)

Если под «сложением» понимается логическая операция дизъюнкции (флаг должен быть равен ИСТИНА, если активна хотя бы одна из опций), используем оператор ИЛИ. В запросах 1С логические операторы могут использоваться непосредственно внутри агрегатных функций или условий.

Рассмотрим пример агрегации нескольких булевых полей:


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

Также при агрегации по группировке МАКСИМУМ от булевого поля вернет ИСТИНА, если хотя бы в одной из сгруппированных строк было значение ИСТИНА.

Нюансы трехзначной логики и работа со значениями NULL

Проанализируем поведение полей, содержащих значение NULL (например, после левого соединения или при использовании объединений таблиц):

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

Оптимизация: условная агрегация вместо объединения запросов

Рассмотрим частую архитектурную ошибку: сбор признаков из одной и той же табличной части через каскадное ОБЪЕДИНИТЬ ВСЕ с последующей группировкой во временной таблице. Многократное чтение одной таблицы перегружает СУБД лишними сканированиями.

Вместо этого разберем реализацию через условную агрегацию (Pivot) за один проход по табличной части документа:


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

Важная рекомендация: поиск по подстроке с маской в начале (ПОДОБНО "%строка%") не использует индексы и приводит к полному сканированию таблицы (Full Scan). При проектировании конфигураций и сложных отчетов фильтрацию и классификацию услуг рекомендуется выполнять по ссылочным полям — реквизитам ВидУслуги, перечислениям или дополнительным реквизитам справочника номенклатуры.

← На главную