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

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

Конструкция «Выбор Когда Тогда Иначе Конец» в запросах 1С

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

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

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

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

Синтаксис конструкции и порядок вычисления

Общая форма записи выглядит так:

ВЫБОР

КОГДА <Условие1>

ТОГДА <Значение1>

КОГДА <Условие2>

ТОГДА <Значение2>

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

КОНЕЦ

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

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

Условия в КОГДА могут включать сравнения, проверку на NULL через ЕСТЬ NULL, операторы В, МЕЖДУ, ПОДОБНО и даже вложенные запросы. Значения в ТОГДА и ИНАЧЕ — литералы, поля источника, параметры или выражения.

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

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

ВЫБОР

КОГДА Заказ.ПометкаУдаления

ТОГДА "Помечен на удаление"

КОГДА Заказ.Проведен

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

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

КОНЕЦ КАК СтатусДокумента

Обратите внимание на порядок: пометка удаления проверяется первой, потому что помеченный документ может одновременно быть проведённым, и без правильного порядка статус вывелся бы неверно. Псевдоним КАК СтатусДокумента даёт колонке понятное имя, которое потом используется в коде или в настройках СКД.

Такой же подход применяется для расчётных величин. Например, скидка в зависимости от суммы:

ВЫБОР

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

ТОГДА Продажи.Сумма * 0.1

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

ТОГДА Продажи.Сумма * 0.05

ИНАЧЕ 0

КОНЕЦ КАК СуммаСкидки

Здесь порядок условий тоже критичен: сначала проверяется больший порог, иначе условие «больше 50000» перехватит все суммы выше 100000, и повышенная скидка никогда не применится.

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

Замена NULL и работа с пустыми значениями

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

ВЫБОР

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

ТОГДА 0

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

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

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

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

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

ВЫБОР КОГДА ТОГДА ИНАЧЕ КОНЕЦ

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

ЕСТЬNULL(поле, замена)

Короткая замена NULL на конкретное значение. Не умеет ничего, кроме проверки на NULL

Вычисление в коде после запроса

Гибче всего, но медленнее на больших выборках и усложняет использование результата в СКД и отчётах

Применение в СКД и динамических списках

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

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

Для отчётов на СКД есть и третий вариант — выражение в ресурсах или в пользовательских полях. Пользовательские поля с типом «Выбор» дают возможность аналитику менять условия прямо в режиме предприятия, без доступа к конфигуратору, что снижает нагрузку на разработчиков.

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

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

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

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

Если в конструкции больше пяти-семи веток КОГДА, это сигнал, что логику лучше вынести в перечисление, дополнительный реквизит или таблицу соответствий и соединить с ней в запросе. Длинные ВЫБОРы тяжело читать и ещё тяжелее поддерживать.
ПЗ
Практическое замечание

Типичные ошибки и как их избежать

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

Третья типичная проблема — смешение типов: например, в одной ветке возвращается число 0, а в другой строка «Нет данных». Запрос упадёт с ошибкой преобразования типов. Четвёртая — сравнение с NULL через знак равенства: Поле = NULL всегда даёт ложь, корректно только Поле ЕСТЬ NULL.

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

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

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

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

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

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

Ошибка о несовместимости типов поля

Колонка результата на тестовых данных
Норма

Каждая ветка срабатывает на своих данных, NULL отсутствуют

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

Есть NULL или одинаковое значение во всех строках

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

Значение ровно на пороге попадает в ожидаемую ветку

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

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

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

Обязательна ли ветка ИНАЧЕ в конструкции ВЫБОР?

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

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

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

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

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

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

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

Работает ли конструкция в динамических списках и СКД?

Да, в обоих случаях. В динамическом списке она пишется прямо в тексте произвольного запроса. В СКД — как в запросе набора данных, так и в вычисляемых полях и пользовательских полях типа «Выбор», где условия можно менять в режиме предприятия без доработки конфигурации.

Как проверить в условии пустую ссылку справочника?

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

Итог

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

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