Разработка и Конфигурация · 10 мин
ВЫБОР КОГДА ТОГДА в запросе 1С: работа с перечислениями
Как использовать конструкцию ВЫБОР КОГДА ТОГДА в запросе 1С для сравнения с перечислением: синтаксис, примеры, типичные ошибки и проверка результата.
Конструкция ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ — это аналог оператора CASE в языке запросов 1С. Она позволяет вернуть разные значения в зависимости от условия прямо в тексте запроса, без постобработки результата в коде. Одна из самых частых задач — сравнение поля со значением перечисления, например вывести текстовое представление статуса документа или подставить коэффициент в зависимости от вида номенклатуры.
Главная сложность при работе с перечислениями — правильное обращение к предопределённым значениям. В запросе нельзя просто написать строку «Проведен» или «Оплачен»: нужно использовать функцию ЗНАЧЕНИЕ() с полным именем значения перечисления. Ошибка в имени приводит либо к отказу выполнения запроса, либо к тихому возврату NULL, что труднее отладить.
Ниже разобран синтаксис конструкции, типовые сценарии с перечислениями, способы проверки результата и ошибки, которые чаще всего встречаются на практике.
Синтаксис конструкции ВЫБОР КОГДА ТОГДА
Полная форма конструкции выглядит так:
ВЫБОР
КОГДА Документ.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыДокумента.Проведен)
ТОГДА "Проведён"
КОГДА Документ.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыДокумента.Отклонен)
ТОГДА "Отклонён"
ИНАЧЕ "В работе"
КОНЕЦ КАК СтатусПредставление
Условия в ветках КОГДА проверяются последовательно сверху вниз. Как только одно из условий выполнилось, остальные ветки не вычисляются. Если ни одно условие не сработало и ветки ИНАЧЕ нет, результат поля будет NULL — это частый источник неожиданных пустых значений в отчётах.
Существует и сокращённая форма, когда сравнивается одно выражение с разными значениями. В языке запросов 1С она записывается через то же ключевое слово ВЫБОР, но условие в каждой ветке всё равно пишется полностью — «короткого» синтаксиса CASE-выражения, как в классическом SQL, в 1С нет.
Как правильно сослаться на значение перечисления
Обращение к значению перечисления выполняется только через ЗНАЧЕНИЕ() с полным путём: Перечисление.ИмяПеречисления.ИмяЗначения. Имя значения — это именно имя, заданное в конфигураторе, а не синоним, который видит пользователь. Если в конфигураторе значение называется НаСогласовании, а синоним — «На согласовании», в запросе нужно писать имя без пробела.
Если значение нужно получить динамически — например, имя перечисления хранится в параметре — функция ЗНАЧЕНИЕ не подойдёт: она принимает только литеральный путь. В этом случае значение перечисления вычисляют в коде встроенного языка через Перечисления.ИмяПеречисления.ИмяЗначения и передают в запрос параметром:
Запрос.УстановитьПараметр("Статус", Перечисления.СтатусыДокумента.Проведен);
Запрос.Текст =
"ВЫБРАТЬ
| ВЫБОР
| КОГДА Док.Статус = &Статус ТОГДА ИСТИНА
| ИНАЧЕ ЛОЖЬ
| КОНЕЦ КАК ЭтоПроведенный
|ИЗ Документ.РеализацияТоваровУслуг КАК Док";
Параметрический вариант предпочтительнее, когда одно и то же значение используется в нескольких местах запроса или когда запрос строится динамически. Он также защищает от опечаток: ошибку в имени значения платформа покажет ещё при обращении к перечислению в коде, а не на этапе выполнения запроса.
Типовые сценарии использования с перечислениями
Вывод представления статуса в отчёт
Самый распространённый сценарий — заменить ссылку на перечисление понятным текстом для пользователя. Хотя у перечисления есть синоним, который платформа показывает автоматически, в отчётах часто требуется другое наименование или группировка нескольких значений в одну категорию:
ВЫБОР
КОГДА Док.Статус В (ЗНАЧЕНИЕ(Перечисление.Статусы.Оплачен),
ЗНАЧЕНИЕ(Перечисление.Статусы.Отгружен))
ТОГДА "Завершённые"
ИНАЧЕ "Активные"
КОНЕЦ КАК ГруппаСтатусов
Расчёт значения в зависимости от вида операции
Вторая частая задача — подставить коэффициент или знак суммы в зависимости от вида документа. Например, в запросе по оборотам приход считается с плюсом, расход — с минусом:
ВЫБОР
КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(Перечисление.ВидыДвижений.Приход)
ТОГДА Обороты.Количество
ИНАЧЕ -Обороты.Количество
КОНЕЦ КАК КоличествоСоЗнаком
Фильтрация и группировка по вычисленному признаку
Результат ВЫБОР можно использовать не только в списке полей, но и в условиях ГДЕ, группировке и упорядочивании — если обернуть вычисление во вложенный запрос или повторить конструкцию. Практичнее вычислить поле один раз во вложенном запросе, а во внешнем уже фильтровать и группировать по нему: текст запроса остаётся читаемым, и оптимизатору СУБД проще построить план.
- 1Определите поле и перечисление, с которым идёт сравнение
- 2Выпишите точные имена значений из конфигуратора
- 3Напишите ветки КОГДА от частных условий к общим
- 4Добавьте ветку ИНАЧЕ с безопасным значением по умолчанию
- 5Проверьте, что все ветки ТОГДА возвращают одинаковый тип
- 6Выполните запрос в консоли и проверьте результат на тестовых данных
Совместимость типов и ветка ИНАЧЕ
Все ветки ТОГДА и ИНАЧЕ должны возвращать значения одного типа или типов, которые платформа способна привести друг к другу. Если одна ветка возвращает строку, а другая — число, запрос может выполниться, но тип поля станет составным, что создаст проблемы при выгрузке в таблицу значений, свёртке и выводе в СКД.
Особое внимание — длине строк. Если в одной ветке возвращается строка из 10 символов, а в другой — из 100, итоговый тип поля платформа определит по веткам, и при последующей обработке возможно усечение. При необходимости тип фиксируют функцией ВЫРАЗИТЬ(... КАК Строка(150)) вокруг всей конструкции ВЫБОР.
Ветку ИНАЧЕ стоит писать всегда, даже если кажется, что перечислены все значения перечисления. В перечисление могут добавить новое значение при обновлении конфигурации — и без ИНАЧЕ все документы с ним молча получат NULL. Осознанное значение по умолчанию («Прочее», 0, исходное значение поля) делает поведение запроса предсказуемым.
Альтернативы конструкции ВЫБОР
ВЫБОР — не единственный способ решить задачу. Если соответствие «значение перечисления → результат» развёрнутое и часто меняется, лучше вынести его в отдельный справочник или регистр сведений и соединять таблицы в запросе. Это позволяет менять соответствия без изменения кода и текста запроса.
Для простых проверок «равно / не равно» в условиях ГДЕ конструкция ВЫБОР вообще не нужна — достаточно прямого сравнения с ЗНАЧЕНИЕ(). А если требуется представление перечисления «как у пользователя», в запросе можно использовать поле Представление ссылки или функцию ПРЕДСТАВЛЕНИЕ(), не расписывая все значения вручную.
Сравнение подходов
Подходит для 2–5 фиксированных значений и простой логики. Ограничение: при добавлении значения в перечисление запрос нужно править вручную.
Подходит, когда значение вычисляется в коде или используется многократно. Ловит опечатки на этапе компиляции модуля.
Подходит для десятков соответствий и частых изменений. Требует дополнительного объекта метаданных и соединения в запросе.
Подходит, когда нужен стандартный синоним значения без своей логики. Не позволяет группировать значения в свои категории.
Проверка результата и типичные ошибки
Отлаживать конструкцию удобнее всего в консоли запросов: выполните запрос на небольшой выборке, где заведомо известны статусы документов, и сверьте вычисленное поле с ожидаемым. Затем проверьте граничные случаи: документы с каждым значением перечисления и, если возможно, записи с NULL в сравниваемом поле — сравнение NULL с любым значением даёт ЛОЖЬ, и такая запись попадёт в ветку ИНАЧЕ.
Как проверить результат
В результате нет неожиданных NULL и значений из ИНАЧЕ там, где должна сработать конкретная ветка
Часть документов попадает в ИНАЧЕ при корректном статусе — значит, имя значения написано с ошибкой или условие не сработало
Один тип во всех строках результата
Смешение строк и чисел, составной тип, усечённые строки
Осознанно обработаны веткой ИНАЧЕ или отдельным условием ЕСТЬ NULL
Потеряны из выборки или неожиданно сгруппированы
FAQ
Можно ли в КОГДА сравнивать поле сразу с несколькими значениями перечисления?
Да, используйте оператор В со списком значений: КОГДА Док.Статус В (ЗНАЧЕНИЕ(Перечисление.Статусы.Оплачен), ЗНАЧЕНИЕ(Перечисление.Статусы.Отгружен)) ТОГДА ... Это компактнее, чем несколько условий через ИЛИ, и работает так же по смыслу.
Что вернёт ВЫБОР, если ни одно условие не выполнилось и ИНАЧЕ нет?
Поле получит значение NULL. В отчётах это выглядит как пустая ячейка, при группировке такие записи собираются в отдельную группу NULL. Чтобы поведение было явным, всегда добавляйте ИНАЧЕ с осознанным значением по умолчанию.
Как сослаться на перечисление, если его имя известно только в строке?
Через ЗНАЧЕНИЕ() это невозможно — функция принимает только литеральный путь в метаданных. Вычислите значение в коде: Перечисления[ИмяПеречисления][ИмяЗначения], и передайте его в запрос параметром через УстановитьПараметр.
Работает ли ВЫБОР в секциях ГДЕ и ИМЕЮЩИЕ?
Да, конструкцию можно использовать в условиях отбора и в агрегатных функциях, например СУММА(ВЫБОР КОГДА ... ТОГДА Сумма ИНАЧЕ 0 КОНЕЦ). Но для читаемости сложные вычисления лучше выносить во вложенный запрос и фильтровать уже готовое поле.
Почему сравнение со строкой «Проведен» не работает?
Поле типа перечисления хранит ссылку на значение перечисления, а не строку. Сравнение ссылки со строкой всегда ложно. Используйте ЗНАЧЕНИЕ(Перечисление.Имя.Значение) или параметр запроса со значением перечисления.
Что важно запомнить
Сравнение с перечислением внутри ВЫБОР КОГДА выполняется через ЗНАЧЕНИЕ() с точным именем значения из конфигуратора или через параметр запроса. Всегда пишите ветку ИНАЧЕ, держите одинаковый тип во всех ветках и проверяйте результат в консоли запросов на тестовых данных, включая записи с NULL.