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

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

ВЫБОР КОГДА ТОГДА в запросах 1С: как работает условный оператор

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

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

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

Ниже разобраны полный синтаксис, варианты условий, работа с NULL и типами данных, использование в СКД и динамических списках, а также ошибки, из-за которых запрос либо падает с ошибкой, либо молча возвращает неожиданный результат.

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

Полная форма оператора выглядит так:

ВЫБОР

КОГДА Условие1 ТОГДА Значение1

КОГДА Условие2 ТОГДА Значение2

ИНАЧЕ ЗначениеПоУмолчанию

КОНЕЦ

Блоков КОГДА может быть сколько угодно. Платформа проверяет условия последовательно сверху вниз и возвращает значение первого истинного условия; остальные ветки не вычисляются. Если ни одно условие не выполнилось, возвращается значение из ИНАЧЕ. Если ветки ИНАЧЕ нет и ни одно условие не сработало, поле получит значение NULL — это частый источник скрытых дефектов в отчётах.

Простой пример — текстовый статус документа:

ВЫБРАТЬ

Док.Ссылка,

ВЫБОР

КОГДА Док.ПометкаУдаления ТОГДА "Помечен на удаление"

КОГДА Док.Проведен ТОГДА "Проведён"

ИНАЧЕ "Не проведён"

КОНЕЦ КАК Статус

ИЗ Документ.РеализацияТоваровУслуг КАК Док

Обратите внимание на порядок условий: пометка удаления проверяется первой, потому что помеченный документ одновременно может быть проведённым. Если поменять ветки местами, помеченный проведённый документ покажется как «Проведён», и логика отчёта исказится.

Какие условия допустимы в КОГДА

В условии КОГДА можно использовать сравнения (=, <>, >, <, >=, <=), проверку В и В ИЕРАРХИИ, оператор ПОДОБНО для строк, проверку ЕСТЬ NULL, логические связки И, ИЛИ, НЕ и скобки для группировки. По сути, допустимо любое логическое выражение, которое разрешено в секции ГДЕ.

Пример с составным условием и проверкой диапазона:

ВЫБОР

КОГДА Продажи.Сумма >= 100000 ТОГДА "Крупная"

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

И Продажи.Количество > 0 ТОГДА "Средняя"

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

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

Для проверки принадлежности списку удобнее В, чем цепочка ИЛИ:

КОГДА Контрагент.Регион В (&СписокРегионов) ТОГДА "Свой регион"

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

Типы значений в ТОГДА и ИНАЧЕ: почему запрос «ругается»

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

Частый конфликт — строки разной длины. Если ТОГДА возвращает строку из 10 символов, а ИНАЧЕ — из 50, платформа может усечь значение по первой ветке. Надёжное решение — явно привести тип через ВЫРАЗИТЬ:

ВЫБОР

КОГДА Док.Проведен ТОГДА ВЫРАЗИТЬ("Проведён" КАК СТРОКА(50))

ИНАЧЕ ВЫРАЗИТЬ("Ожидает проведения" КАК СТРОКА(50))

КОНЕЦ КАК Статус

Ещё одна ловушка — смешение ссылки и значения NULL. Если в одной ветке возвращается ссылка на справочник, а в ИНАЧЕ стоит NULL, поле станет составного типа. Лучше подставить пустую ссылку нужного типа: ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка). Тогда тип поля останется чистым, а проверка на пустоту в дальнейшем упростится.

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

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

Конструкция ВЫБОР особенно полезна вместе с левыми соединениями, где отсутствующая запись даёт NULL в полях правой таблицы. Например, нужно показать остаток, а для товаров без движений — ноль:

ВЫБОР

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

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

КОНЕЦ КАК Остаток

Тот же результат короче даёт функция ЕСТЬNULL(Остатки.КоличествоОстаток, 0). Разница в гибкости: ЕСТЬNULL принимает только два аргумента, тогда как ВЫБОР позволяет строить многоступенчатую логику — например, NULL заменить нулём, отрицательное значение пометить как «пересорт», а положительное оставить как есть.

Важно помнить: сравнение Поле = NULL в условии КОГДА всегда даёт ложь, потому что NULL не равен ничему, включая сам себя. Проверять отсутствие значения нужно только оператором ЕСТЬ NULL.

ВЫБОР или ЕСТЬNULL

ЕСТЬNULL(Поле, Значение)

Короткая замена NULL на конкретное значение; подходит для простой подстановки, но не поддерживает несколько условий

ВЫБОР КОГДА ТОГДА

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

ВЫБОР в СКД, динамических списках и вычисляемых полях

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

СУММА(ВЫБОР

КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)

ТОГДА Обороты.Количество

ИНАЧЕ 0

КОНЕЦ) КАК Приход

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

Во встроенном коде (не в запросе) аналогом служит обычный Если ... Тогда ... Иначе ... КонецЕсли; либо тернарный оператор через функцию ?(Условие, Значение1, Значение2) — она доступна в выражениях встроенного языка и удобна для коротких подстановок.

Производительность и проверка результата

Сама по себе конструкция ВЫБОР почти не влияет на скорость запроса — она вычисляется построчно при формировании выборки. Но косвенные эффекты есть. Если условие в КОГДА использует функции над полями (например, ПОДСТРОКА или ВЫРАЗИТЬ), СУБД может отказаться от индексного поиска при использовании того же выражения в соединениях или отборах. Поэтому ВЫБОР лучше размещать в списке выборки, а не в секции ГДЕ и не в условиях соединения.

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

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

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

Значения поля в выборке
Норма

Каждая запись получила значение ожидаемой ветки, пустых NULL нет

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

В поле встречаются NULL или значения не из списка ТОГДА/ИНАЧЕ

Тип поля результата
Норма

Один тип у всей колонки, итоги и сортировка работают

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

Составной тип, строки усечены, итог по полю не считается

Записи без совпадения условий
Норма

Получили значение ИНАЧЕ

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

Выпали из выборки или показали NULL

FAQ

Обязательна ли ветка ИНАЧЕ?

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

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

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

Почему строка обрезалась, хотя в ТОГДА указан полный текст?

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

Можно ли использовать ВЫБОР в секции ГДЕ?

Технически да, например ГДЕ (ВЫБОР КОГДА ... КОНЕЦ) = &Значение. Но такой отбор почти всегда отключает использование индексов и замедляет запрос на больших таблицах. Предпочтительнее переписать условие через обычные логические связки И/ИЛИ или отфильтровать данные на уровне СКД.

Чем ВЫБОР в запросе отличается от функции ?() в коде?

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

Как сгруппировать результат по полю, вычисленному через ВЫБОР?

Дайте конструкции псевдоним через КАК и используйте этот псевдоним в секции СГРУППИРОВАТЬ ПО либо вынесите вычисление во вложенный запрос, а группировку выполните во внешнем. В СКД достаточно включить поле в группировку настроек — платформа сгруппирует сама.

Итог

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

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