К статье
Практический материал

Разработка и Конфигурация · 10 мин

Конструкция ВЫБОР КОГДА в языке запросов 1С: синтаксис и практика

Как использовать конструкцию ВЫБОР КОГДА в языке запросов 1С: синтаксис, примеры с ИНАЧЕ и КОНЕЦ, типичные ошибки, проверка результата и ответы на частые вопросы.

Конструкция ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ — это аналог оператора CASE в языке запросов 1С. Она позволяет прямо в тексте запроса возвращать разные значения в зависимости от условий, не прибегая к постобработке результата в коде. Это один из самых востребованных приёмов при разработке отчётов, динамических списков и выборок для обмена данными.

Типовая задача: в отчёте по продажам нужно вывести не внутреннее перечисление статуса, а понятную пользователю строку «Оплачен», «Частично оплачен» или «Не оплачен». Без ВЫБОР пришлось бы обходить выборку в цикле и формировать дополнительную колонку программно. С конструкцией ВЫБОР всё решается одним полем запроса, что быстрее и проще в сопровождении.

Ниже разобраны синтаксис, практические сценарии, ограничения конструкции, типичные ошибки и способы проверить, что запрос возвращает именно те значения, которые ожидались.

Синтаксис конструкции ВЫБОР КОГДА

Полная форма конструкции выглядит так: ключевое слово ВЫБОР, затем одна или несколько пар КОГДА условие ТОГДА выражение, необязательная ветка ИНАЧЕ выражение и обязательное завершение словом КОНЕЦ. Условием может быть любое логическое выражение: сравнение, проверка на NULL, операторы И, ИЛИ, НЕ.

ВЫБОР

КОГДА Продажи.Сумма >= 100000

ТОГДА "Крупная"

КОГДА Продажи.Сумма >= 10000

ТОГДА "Средняя"

ИНАЧЕ "Мелкая"

КОНЕЦ КАК КатегорияСделки

Важно понимать порядок вычисления: условия проверяются последовательно сверху вниз, и выполняется только ветка первого истинного условия. Если в примере выше поменять строки местами и поставить проверку >= 10000 первой, то категория «Крупная» не будет присвоена никогда — все суммы выше ста тысяч попадут в «Средняя». Порядок условий — частая причина логических ошибок.

Если ни одно условие не выполнилось и ветка ИНАЧЕ отсутствует, поле получит значение НЕОПРЕДЕЛЕНО. Это не всегда очевидно при чтении результата, поэтому ветку ИНАЧЕ рекомендуется писать всегда, даже если она возвращает пустую строку или NULL.

Базовые примеры для типовых задач

Самый частый сценарий — замена ссылки на перечисление или служебного кода читаемым текстом. Например, в запросе к документам нужно показать вид операции словами, а не ссылкой:

ВЫБОР

КОГДА Реализация.ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОпераций.Продажа)

ТОГДА "Продажа товаров"

КОГДА Реализация.ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОпераций.Возврат)

ТОГДА "Возврат от покупателя"

ИНАЧЕ "Прочее"

КОНЕЦ КАК ВидОперацииТекстом

Второй сценарий — вычисляемые числовые поля. Например, расчёт скидки по шкале: чем больше сумма документа, тем выше процент. Здесь ВЫБОР возвращает число, которое дальше участвует в арифметике запроса: Продажи.Сумма * (ВЫБОР ... КОНЕЦ) / 100 КАК СуммаСкидки. Такой подход позволяет выполнить весь расчёт на стороне СУБД.

Третий сценарий — признаки булевского типа для отборов и группировок. Например, поле «Просрочен», которое сравнивает дату оплаты с текущей датой, а затем используется в секции СГРУППИРОВАТЬ ПО или в итогах СКД. Это удобнее, чем вычислять признак в коде после выполнения запроса.

Как добавить ВЫБОР КОГДА в запрос
  1. 1
    Определите, какое поле должно зависеть от условия, и какие значения оно может принимать
  2. 2
    Запишите условия КОГДА в порядке от более частного к более общему
  3. 3
    Убедитесь, что все выражения ТОГДА и ИНАЧЕ имеют одинаковый или совместимый тип
  4. 4
    Добавьте ветку ИНАЧЕ с безопасным значением по умолчанию
  5. 5
    Выполните запрос в консоли запросов и проверьте результат на граничных значениях

Работа с NULL и соединениями таблиц

При левом соединении таблиц поля из присоединённой таблицы могут содержать NULL, если пары не нашлось. Прямое сравнение КОГДА Поле = 0 для NULL-значения не сработает: любое сравнение с NULL даёт не ИСТИНА и не ЛОЖЬ, а неопределённый результат, и условие считается невыполненным. Поэтому для проверки NULL используют конструкцию ЕСТЬ NULL или функцию ЕСТЬNULL() внутри условия.

ВЫБОР

КОГДА Остатки.Количество ЕСТЬ NULL

ТОГДА 0

КОГДА Остатки.Количество < 0

ТОГДА 0

ИНАЧЕ Остатки.Количество

КОНЕЦ КАК ДоступныйОстаток

Альтернатива — обернуть поле в ЕСТЬNULL(Остатки.Количество, 0) и упростить сам ВЫБОР. Оба подхода рабочие; выбор зависит от читаемости запроса. Если условие одно, ЕСТЬNULL компактнее. Если условий несколько и они разнородные, явный ВЫБОР с проверкой ЕСТЬ NULL понятнее при сопровождении.

Когда ВЫБОР лучше заменить другими средствами

Конструкция ВЫБОР не всегда оптимальна. Если ветвление нужно только для подстановки значения при NULL, короче использовать ЕСТЬNULL(поле, значение). Если нужно выбрать первое непустое значение из нескольких полей, в ряде случаев удобнее последовательные соединения или объединение запросов.

Если количество ветвей КОГДА превышает десяток и условия ссылаются на один и тот же справочник, стоит подумать о переносе логики в данные: например, хранить расшифровку в реквизите справочника и соединять таблицы вместо перечисления значений в тексте запроса. Это избавляет от правки запроса при добавлении новых значений пользователями.

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

Чем заменить ВЫБОР

ЕСТЬNULL(поле, значение)

Подходит для единственной задачи — подстановки значения вместо NULL. Не работает с произвольными условиями.

Соединение со справочником

Подходит, когда расшифровка значений хранится в данных. Требует поддержки данных, зато не нужно править запрос.

Временная таблица + второй запрос

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

Проверка результата и граничные случаи

После написания запроса с ВЫБОР проверку стоит делать в консоли запросов на реальных данных, включая граничные значения. Минимальный набор проверок: значение ровно на границе условия (например, сумма ровно 100000), значение ниже всех порогов, NULL в проверяемом поле и значение, не предусмотренное ни одной веткой КОГДА.

Полезно временно добавить в выборку само проверяемое поле рядом с вычисляемым — так сразу видно, в какую ветку попала каждая строка. Если в результате встречается НЕОПРЕДЕЛЕНО, значит, какая-то строка не попала ни в одно условие и ветка ИНАЧЕ отсутствует.

Для отчётов на СКД дополнительно проверьте, как вычисляемое поле ведёт себя в группировках и итогах. Агрегирование поля, построенного на ВЫБОР, может требовать явного указания выражения итога, например СУММА(...), иначе в итоговых строках появятся пустые значения.

Контрольные точки

Как проверить результат

Граничное значение условия
Норма

Строка попадает в ожидаемую ветку согласно знаку сравнения

Тревожный признак

Значение на границе уходит в соседнюю категорию — проверьте &gt;= и &gt;

NULL в исходном поле
Норма

Строка обрабатывается веткой ЕСТЬ NULL или ЕСТЬNULL

Тревожный признак

Строка молча попадает в ИНАЧЕ с неверным значением

Поле результата в выборке
Норма

Все строки имеют одно из заданных значений

Тревожный признак

Встречается НЕОПРЕДЕЛЕНО — нет ветки ИНАЧЕ

Типичные ошибки и ограничения

Главная ошибка — несовместимость типов возвращаемых значений. Если одна ветка возвращает строку, а другая число, платформа может отказаться выполнять запрос или привести значения неожиданным образом. Правило простое: все выражения ТОГДА и ИНАЧЕ должны быть одного типа или приводиться к нему явно.

Вторая группа ошибок — логическая: перепутанный порядок условий, пропущенная ветка ИНАЧЕ, сравнение с NULL через равенство. Эти ошибки не вызывают падения запроса, поэтому обнаруживаются только при внимательной проверке данных.

Из ограничений стоит помнить: условия КОГДА не могут содержать агрегатные функции напрямую в секции полей выборки — для таких проверок используется секция ИМЕЮЩИЕ или вложенный запрос. Также чрезмерно длинные цепочки ВЫБОР ухудшают читаемость и могут замедлять выполнение на больших таблицах, поэтому сложную логику лучше выносить в данные или временные таблицы.

Типичные ошибки
01
Условия записаны от общего к частному — частные случаи никогда не срабатывают
02
Нет ветки ИНАЧЕ — часть строк получает НЕОПРЕДЕЛЕНО и ломает дальнейшие вычисления
03
Сравнение с NULL через = — условие никогда не выполняется, строки уходят в ИНАЧЕ
04
Разные типы значений в ветках ТОГДА — ошибка выполнения или неявное приведение типов
05
Десятки ветвей КОГДА по справочнику — запрос приходится править при каждом новом значении в базе
Итог

Что важно запомнить

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

Частые вопросы о ВЫБОР КОГДА в запросах 1С

Можно ли вкладывать один ВЫБОР внутрь другого?

Да, вложенные конструкции допустимы: выражение ТОГДА или ИНАЧЕ может содержать ещё один ВЫБОР. Однако уже при двух уровнях вложенности запрос заметно теряет читаемость. Если логика разветвляется глубже, лучше разбить вычисление на шаги через временные таблицы или перенести часть условий в данные.

Чем ВЫБОР в запросе отличается от оператора Если во встроенном языке?

ВЫБОР работает внутри запроса и вычисляется на уровне СУБД для каждой строки выборки, без обмена данными с кодом. Оператор Если выполняется уже после получения результата. Для больших выборок ВЫБОР эффективнее: не нужен цикл обхода и дополнительная обработка каждой строки.

Как использовать ВЫБОР в секции условий ГДЕ?

Напрямую ВЫБОР в ГДЕ обычно не нужен — там достаточно логических операторов И, ИЛИ. Но можно сравнивать поле с результатом ВЫБОР, например: ГДЕ Заказ.Статус = ВЫБОР КОГДА &ТолькоАктивные ТОГДА ЗНАЧЕНИЕ(...) ИНАЧЕ Заказ.Статус КОНЕЦ. Это приём для необязательных отборов по параметру.

Почему запрос с ВЫБОР выдаёт ошибку о несовместимости типов?

Потому что ветки возвращают значения разных типов, которые платформа не может привести к одному. Например, строка и ссылка на справочник. Решение — привести значения к общему типу явно: использовать ПРЕДСТАВЛЕНИЕ() для ссылок, пустую строку вместо NULL или одинаковый числовой формат во всех ветках.

Работает ли ВЫБОР КОГДА в динамических списках и СКД?

Да, конструкция полностью поддерживается в тексте запроса динамического списка и в наборе данных СКД. В СКД вычисляемое поле на основе ВЫБОР можно использовать в отборах, группировках и ресурсах, но для итогов может потребоваться явно задать выражение агрегирования.