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

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

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

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

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

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

Ниже разобран полный синтаксис, варианты с несколькими условиями, вложенные ВЫБОР, работа с NULL и типами данных, а также ошибки, из-за которых запрос падает с ошибкой или возвращает неожиданный результат.

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

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

ВЫБОР

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

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

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

КОНЕЦ

Условия проверяются сверху вниз, и возвращается значение первого выполнившегося условия. Если ни одно условие не сработало и ветка ИНАЧЕ отсутствует, результатом будет NULL. Слово КОНЕЦ обязательно — его пропуск является одной из самых частых синтаксических ошибок.

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

Простой пример: выбор значения по одному условию

Классическая задача — вывести текстовое представление признака вместо булева значения или кода:

ВЫБРАТЬ

Номенклатура.Наименование КАК Товар,

ВЫБОР

КОГДА Номенклатура.ЭтоГруппа

ТОГДА "Группа"

ИНАЧЕ "Элемент"

КОНЕЦ КАК ВидЗаписи

ИЗ

Справочник.Номенклатура КАК Номенклатура

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

Ещё один частый сценарий — замена NULL на значение по умолчанию при левом соединении:

ВЫБОР

КОГДА Цены.Цена ЕСТЬ NULL

ТОГДА 0

ИНАЧЕ Цены.Цена

КОНЕЦ КАК Цена

Для этой конкретной задачи есть и более короткая функция ЕСТЬNULL(Цены.Цена, 0), но ВЫБОР гибче: он позволяет проверять любые условия, а не только NULL.

Несколько условий и порядок их проверки

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

ВЫБОР

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

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

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

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

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

КОНЕЦ КАК КатегорияПродажи

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

В условиях допустимы любые логические выражения языка запросов: сравнения, И, ИЛИ, НЕ, проверки В ИЕРАРХИИ, ПОДОБНО, МЕЖДУ, ЕСТЬ NULL. Например:

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

И НЕ Контрагент.ПометкаУдаления

ТОГДА "Активный региональный"

Типичные ошибки
01
Неправильный порядок условий: общее условие стоит выше частного, и частная ветка никогда не срабатывает
02
Пропущено слово КОНЕЦ — запрос не проходит проверку синтаксиса
03
Нет ветки ИНАЧЕ: при несрабатывании всех условий поле возвращает NULL, что ломает сортировку и группировку
04
Несовместимые типы значений в ветках: строка в одной ветке, число в другой — ошибка при выполнении запроса

Совместимость типов значений в ветках

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

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

ВЫБОР

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

ТОГДА "Нет данных"

ИНАЧЕ ПРЕДСТАВЛЕНИЕ(Остатки.Количество)

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

Учтите, что после приведения к строке поле теряет возможность числовой сортировки и агрегации — строка «9» будет стоять после строки «10». Поэтому такой приём оправдан только для финального вывода в отчёт, а не для промежуточных расчётов.

Вложенные ВЫБОР и ВЫБОР внутри агрегатных функций

Конструкции ВЫБОР можно вкладывать друг в друга, когда логика разветвляется по нескольким измерениям:

ВЫБОР

КОГДА Документ.Проведен

ТОГДА ВЫБОР

КОГДА Документ.Сумма > 0

ТОГДА "Проведён с суммой"

ИНАЧЕ "Проведён без суммы"

КОНЕЦ

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

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

Глубокая вложенность быстро снижает читаемость. Практический предел — два уровня; дальше лучше пересмотреть логику или разбить вычисление на несколько полей.

Особенно мощный приём — ВЫБОР внутри агрегатной функции. Так можно посчитать суммы по разным категориям в одном проходе без соединений и объединений:

ВЫБРАТЬ

Продажи.Менеджер КАК Менеджер,

СУММА(ВЫБОР

КОГДА Продажи.Оплачено ТОГДА Продажи.Сумма

ИНАЧЕ 0

КОНЕЦ) КАК ОплаченнаяСумма,

СУММА(ВЫБОР

КОГДА НЕ Продажи.Оплачено ТОГДА Продажи.Сумма

ИНАЧЕ 0

КОНЕЦ) КАК ДебиторскаяЗадолженность

ИЗ

РегистрНакопления.Продажи КАК Продажи

СГРУППИРОВАТЬ ПО

Продажи.Менеджер

Обратите внимание: в ветке ИНАЧЕ внутри агрегата нужно возвращать 0, а не опускать ветку. Иначе в сумму попадут NULL-значения, и хотя СУММА их игнорирует, результат для пустых групп может отличаться от ожидаемого.

ВЫБОР в секции ГДЕ, соединениях и параметрах

Хотя в секции ГДЕ обычно пишут прямые условия, ВЫБОР там тоже допустим — как часть логического выражения. Например, отбор по вычисляемому признаку:

ГДЕ

ВЫБОР

КОГДА Заказы.Сумма > 50000 ТОГДА "Крупный"

ИНАЧЕ "Обычный"

КОНЕЦ = &ТипЗаказа

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

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

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

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

Граничные значения — самое слабое место. Если условие «Сумма >= 10000», проверьте строки с суммой ровно 10000, 9999.99 и NULL. NULL в сравнении даёт не ИСТИНА и не ЛОЖЬ, а неопределённость: условие «КОГДА NULL > 100» не выполнится, и запись уйдёт в ветку ИНАЧЕ. Если такое поведение нежелательно, оберните поле в ЕСТЬNULL внутри условия.

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

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

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

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

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

Появились NULL при наличии ветки ИНАЧЕ или строки в неправильных категориях

Граничные значения
Норма

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

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

Пороговые строки уходят не туда из-за путаницы строгого и нестрогого сравнения

Тип поля
Норма

Все ветки возвращают один тип, поле пригодно для сортировки и группировки

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

Ошибка несовместимости типов при выполнении запроса

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

Не каждая условная задача требует ВЫБОР. Для подстановки значения вместо NULL короче и читабельнее функция ЕСТЬNULL(Поле, ЗначениеПоУмолчанию). Для сопоставления по множеству значений часто удобнее соединение с регистром сведений или временной таблицей соответствий — так правила можно менять без правки запроса.

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

Сравнение вариантов

ВЫБОР КОГДА

Универсальное решение для любых условий прямо в запросе; ограничение — логика зашита в код

ЕСТЬNULL

Короткая замена NULL значением по умолчанию; не умеет ничего, кроме проверки на NULL

Соединение с регистром сведений

Правила соответствия хранятся в данных и меняются без правки кода; требует дополнительной таблицы и соединения

Вычисляемое поле СКД

Гибкие выражения на языке 1С в отчёте; вычисляется не на СУБД, что медленнее на больших данных

Итог

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

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

Частые вопросы

Можно ли использовать ВЫБОР без ветки ИНАЧЕ?

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

Чем ВЫБОР отличается от ЕСТЬNULL?

ЕСТЬNULL(Поле, Значение) — частный случай: заменяет NULL указанным значением. ВЫБОР проверяет любые условия и возвращает разные значения для разных ситуаций. Если задача — только подставить значение вместо NULL, используйте ЕСТЬNULL: запись короче и понятнее.

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

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

Можно ли использовать ВЫБОР в секции СГРУППИРОВАТЬ ПО?

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

Почему условие внутри ВЫБОР не срабатывает, хотя данные есть?

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

Влияет ли ВЫБОР на производительность запроса?

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