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

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

ВЫБОР КОГДА ТОГДА в запросе 1С: работа с перечислениями

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

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

Главная сложность при работе с перечислениями — правильное обращение к предопределённым значениям. В запросе нельзя просто написать строку «Проведен» или «Оплачен»: нужно использовать функцию ЗНАЧЕНИЕ() с полным именем значения перечисления. Ошибка в имени приводит либо к отказу выполнения запроса, либо к тихому возврату NULL, что труднее отладить.

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

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

Полная форма конструкции выглядит так:

ВЫБОР

КОГДА Документ.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыДокумента.Проведен)

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

КОГДА Документ.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыДокумента.Отклонен)

ТОГДА "Отклонён"

ИНАЧЕ "В работе"

КОНЕЦ КАК СтатусПредставление

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

Существует и сокращённая форма, когда сравнивается одно выражение с разными значениями. В языке запросов 1С она записывается через то же ключевое слово ВЫБОР, но условие в каждой ветке всё равно пишется полностью — «короткого» синтаксиса CASE-выражения, как в классическом SQL, в 1С нет.

Как правильно сослаться на значение перечисления

Обращение к значению перечисления выполняется только через ЗНАЧЕНИЕ() с полным путём: Перечисление.ИмяПеречисления.ИмяЗначения. Имя значения — это именно имя, заданное в конфигураторе, а не синоним, который видит пользователь. Если в конфигураторе значение называется НаСогласовании, а синоним — «На согласовании», в запросе нужно писать имя без пробела.

Если значение нужно получить динамически — например, имя перечисления хранится в параметре — функция ЗНАЧЕНИЕ не подойдёт: она принимает только литеральный путь. В этом случае значение перечисления вычисляют в коде встроенного языка через Перечисления.ИмяПеречисления.ИмяЗначения и передают в запрос параметром:

Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыДокумента.Проведен);

Запрос.Текст =

"ВЫБРАТЬ

| ВЫБОР

| КОГДА Док.Статус = &Статус ТОГДА ИСТИНА

| ИНАЧЕ ЛОЖЬ

| КОНЕЦ КАК ЭтоПроведенный

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

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

Типовые сценарии использования с перечислениями

Вывод представления статуса в отчёт

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

ВЫБОР

КОГДА Док.Статус В (ЗНАЧЕНИЕ(Перечисление.Статусы.Оплачен),

ЗНАЧЕНИЕ(Перечисление.Статусы.Отгружен))

ТОГДА "Завершённые"

ИНАЧЕ "Активные"

КОНЕЦ КАК ГруппаСтатусов

Расчёт значения в зависимости от вида операции

Вторая частая задача — подставить коэффициент или знак суммы в зависимости от вида документа. Например, в запросе по оборотам приход считается с плюсом, расход — с минусом:

ВЫБОР

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

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

ИНАЧЕ -Обороты.Количество

КОНЕЦ КАК КоличествоСоЗнаком

Фильтрация и группировка по вычисленному признаку

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

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

Совместимость типов и ветка ИНАЧЕ

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

Особое внимание — длине строк. Если в одной ветке возвращается строка из 10 символов, а в другой — из 100, итоговый тип поля платформа определит по веткам, и при последующей обработке возможно усечение. При необходимости тип фиксируют функцией ВЫРАЗИТЬ(... КАК Строка(150)) вокруг всей конструкции ВЫБОР.

Ветку ИНАЧЕ стоит писать всегда, даже если кажется, что перечислены все значения перечисления. В перечисление могут добавить новое значение при обновлении конфигурации — и без ИНАЧЕ все документы с ним молча получат NULL. Осознанное значение по умолчанию («Прочее», 0, исходное значение поля) делает поведение запроса предсказуемым.

Альтернативы конструкции ВЫБОР

ВЫБОР — не единственный способ решить задачу. Если соответствие «значение перечисления → результат» развёрнутое и часто меняется, лучше вынести его в отдельный справочник или регистр сведений и соединять таблицы в запросе. Это позволяет менять соответствия без изменения кода и текста запроса.

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

Сравнение подходов

ВЫБОР КОГДА с ЗНАЧЕНИЕ()

Подходит для 2–5 фиксированных значений и простой логики. Ограничение: при добавлении значения в перечисление запрос нужно править вручную.

Параметр запроса

Подходит, когда значение вычисляется в коде или используется многократно. Ловит опечатки на этапе компиляции модуля.

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

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

ПРЕДСТАВЛЕНИЕ()

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

Проверка результата и типичные ошибки

Отлаживать конструкцию удобнее всего в консоли запросов: выполните запрос на небольшой выборке, где заведомо известны статусы документов, и сверьте вычисленное поле с ожидаемым. Затем проверьте граничные случаи: документы с каждым значением перечисления и, если возможно, записи с NULL в сравниваемом поле — сравнение NULL с любым значением даёт ЛОЖЬ, и такая запись попадёт в ветку ИНАЧЕ.

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

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

Все значения перечисления покрыты условиями
Норма

В результате нет неожиданных NULL и значений из ИНАЧЕ там, где должна сработать конкретная ветка

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

Часть документов попадает в ИНАЧЕ при корректном статусе — значит, имя значения написано с ошибкой или условие не сработало

Тип вычисляемого поля
Норма

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

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

Смешение строк и чисел, составной тип, усечённые строки

Записи с NULL в поле сравнения
Норма

Осознанно обработаны веткой ИНАЧЕ или отдельным условием ЕСТЬ NULL

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

Потеряны из выборки или неожиданно сгруппированы

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

FAQ

Можно ли в КОГДА сравнивать поле сразу с несколькими значениями перечисления?

Да, используйте оператор В со списком значений: КОГДА Док.Статус В (ЗНАЧЕНИЕ(Перечисление.Статусы.Оплачен), ЗНАЧЕНИЕ(Перечисление.Статусы.Отгружен)) ТОГДА ... Это компактнее, чем несколько условий через ИЛИ, и работает так же по смыслу.

Что вернёт ВЫБОР, если ни одно условие не выполнилось и ИНАЧЕ нет?

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

Как сослаться на перечисление, если его имя известно только в строке?

Через ЗНАЧЕНИЕ() это невозможно — функция принимает только литеральный путь в метаданных. Вычислите значение в коде: Перечисления[ИмяПеречисления][ИмяЗначения], и передайте его в запрос параметром через УстановитьПараметр.

Работает ли ВЫБОР в секциях ГДЕ и ИМЕЮЩИЕ?

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

Почему сравнение со строкой «Проведен» не работает?

Поле типа перечисления хранит ссылку на значение перечисления, а не строку. Сравнение ссылки со строкой всегда ложно. Используйте ЗНАЧЕНИЕ(Перечисление.Имя.Значение) или параметр запроса со значением перечисления.

Итог

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

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