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

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

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

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

Оператор ВЫБОР в языке запросов 1С — это аналог конструкции CASE из классического SQL. Он позволяет прямо в тексте запроса задать условную логику: проверить значение поля и в зависимости от результата вернуть то или иное значение. Это один из самых востребованных приёмов при построении отчётов, динамических списков и выборок для обмена данными.

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

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

Синтаксис оператора ВЫБОР: две формы записи

В языке запросов 1С существует две формы оператора ВЫБОР. Первая — поисковая, когда в каждом КОГДА записывается полноценное логическое условие. Вторая — простая, когда сразу после ВЫБОР указывается выражение, а в КОГДА перечисляются значения для сравнения на равенство.

bsl
ВЫБРАТЬ
	ВЫБОР
		КОГДА Заказы.Сумма > 100000
			ТОГДА "Крупный"
		КОГДА Заказы.Сумма > 10000
			ТОГДА "Средний"
		ИНАЧЕ "Мелкий"
	КОНЕЦ КАК КатегорияЗаказа
ИЗ
	Документ.ЗаказПокупателя КАК Заказы

Условия проверяются строго сверху вниз. Как только одно из условий КОГДА оказалось истинным, выполняется соответствующее ТОГДА, а остальные ветви не вычисляются. Поэтому порядок условий имеет значение: более частные условия нужно ставить выше более общих. Если в примере выше поменять ветви местами, заказы на сумму больше 100000 попадут в категорию «Средний», потому что условие «больше 10000» сработает раньше.

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

bsl
ВЫБРАТЬ
	ВЫБОР Контрагенты.ЮрФизЛицо
		КОГДА ЗНАЧЕНИЕ(Перечисление.ЮрФизЛицо.ЮрЛицо)
			ТОГДА "Организация"
		КОГДА ЗНАЧЕНИЕ(Перечисление.ЮрФизЛицо.ФизЛицо)
			ТОГДА "Физическое лицо"
		ИНАЧЕ "Не определено"
	КОНЕЦ КАК ВидКонтрагента
ИЗ
	Справочник.Контрагенты КАК Контрагенты

Зачем нужно ИНАЧЕ и что происходит без него

Ветвь ИНАЧЕ формально необязательна, но на практике её следует писать всегда. Если ни одно условие КОГДА не выполнилось и ИНАЧЕ отсутствует, оператор вернёт NULL. Это значение потом «протекает» дальше: попадает в группировки, соединения, вычисляемые поля СКД и вызывает трудноотлаживаемые ошибки.

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

Если по смыслу задачи «значение по умолчанию» не нужно, всё равно лучше явно написать ИНАЧЕ NULL или ИНАЧЕ с нейтральным значением (пустая строка, ноль). Так поведение запроса становится предсказуемым, а намерение разработчика — очевидным при чтении кода.

Практические сценарии применения

Замена значений перечисления на понятные подписи

Классическая задача — вывести в отчёт человекочитаемый статус вместо ссылки на перечисление или вместо технического кода. Особенно это полезно при выгрузке данных во внешние системы, где ссылочные значения 1С ничего не значат.

bsl
ВЫБРАТЬ
	Реализация.Номер КАК Номер,
	ВЫБОР
		КОГДА Реализация.Проведен
			ТОГДА "Проведён"
		КОГДА Реализация.ПометкаУдаления
			ТОГДА "Помечен на удаление"
		ИНАЧЕ "Черновик"
	КОНЕЦ КАК СостояниеДокумента
ИЗ
	Документ.РеализацияТоваровУслуг КАК Реализация

Вычисление значения по диапазонам

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

При работе с диапазонами важно помнить про порядок условий и про граничные значения. Условие «больше 100» и «больше или равно 100» — разные вещи: значение ровно 100 попадёт в разные ветви. Согласуйте границы с постановкой задачи и зафиксируйте их в комментарии к запросу.

Подмена NULL через ВЫБОР и ЕСТЬ NULL

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

Чем подменять NULL

ЕСТЬNULL(Поле, 0)

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

ВЫБОР КОГДА Поле ЕСТЬ NULL

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

ВЫБОР в секциях ГДЕ, ИМЕЮЩИЕ и соединениях

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

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

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

Ограничения и влияние на производительность

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

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

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

Типичные ошибки и как их проверить

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

Отдельно стоит упомянуть сравнение с NULL. В логике запросов NULL не равен ничему, включая сам себя, поэтому условие вида «КОГДА Таблица.Поле = NULL» молча не сработает ни для одной строки. Правильная запись — «КОГДА Таблица.Поле ЕСТЬ NULL». Эта ошибка особенно коварна, потому что запрос выполняется без сообщений об ошибке, просто результат неверный.

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

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

Число строк в результате
Норма

Совпадает с числом строк до добавления ВЫБОР

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

Строки появились или пропали — проблема в соединениях или NULL

Категории на граничных значениях
Норма

Значения на границах диапазонов попадают в ожидаемые ветви

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

Граничные значения уходят не туда — перепутан порядок КОГДА или знаки сравнения

Значения NULL в вычисленной колонке
Норма

NULL отсутствуют или присутствуют осознанно

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

Неожиданные NULL — забыто ИНАЧЕ или не учтены пустые значения

FAQ

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

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

Можно ли использовать ВЫБОР внутри агрегатной функции?

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

Почему условие «Поле = NULL» не срабатывает?

Потому что NULL в логике запросов не равен никакому значению, включая NULL. Для проверки используйте оператор ЕСТЬ NULL: «КОГДА Поле ЕСТЬ NULL ТОГДА ...». Это одна из самых частых причин «тихо» неверных результатов.

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

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

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

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

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

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

Итог

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

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