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

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

ВЫБОР КОГДА ТОГДА в запросах 1С 8.3: полное руководство с примерами

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

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

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

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

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

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

ВЫБОР

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

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

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

КОНЕЦ

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

Конструкция может использоваться в списке выбираемых полей, в условии ГДЕ, в итогах и группировках. Минимальный рабочий пример:

ВЫБРАТЬ

Док.Ссылка,

ВЫБОР

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

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

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

ИЗ

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

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

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

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

ВЫБОР

КОГДА Продажи.Сумма >= 1000000 ТОГДА "VIP"

КОГДА Продажи.Сумма >= 100000 ТОГДА "Крупный"

КОГДА Продажи.Сумма > 0 ТОГДА "Обычный"

ИНАЧЕ "Без продаж"

КОНЕЦ КАК КатегорияКлиента

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

Внутри одного условия допускаются логические операции И, ИЛИ, НЕ и вложенные скобки:

КОГДА Док.Проведен И НЕ Док.ПометкаУдаления ТОГДА "Активен"

Старайтесь не перегружать одну ветку множеством условий: запрос с пятью-шестью вложенными И/ИЛИ тяжело читать и отлаживать. Если логика разрастается, часто удобнее вынести её в соединение со вспомогательной таблицей или пересмотреть структуру запроса.

Сравнение с перечислениями, NULL и пустыми значениями

Одна из самых частых задач — сравнение поля со значением перечисления. Ссылку на перечисление указывают через конструкцию ЗНАЧЕНИЕ:

ВЫБОР

КОГДА Док.ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОпераций.Продажа)

ТОГДА "Продажа"

КОГДА Док.ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОпераций.Возврат)

ТОГДА "Возврат"

ИНАЧЕ "Прочее"

КОНЕЦ

Отдельная тонкость — NULL. Он появляется в результатах левых соединений, когда в присоединяемой таблице не нашлось подходящей строки. Прямое сравнение = NULL в языке запросов не работает так, как ожидается: любое сравнение с NULL даёт неопределённый результат, и ветка не сработает. Правильный вариант — оператор ЕСТЬ NULL:

ВЫБОР

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

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

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

Для подстановки значения вместо NULL также существует функция ЕСТЬNULL(Поле, ЗначениеПоУмолчанию) — она короче и предпочтительнее, если нужно просто заменить NULL, без сложной логики. Не путайте NULL с пустой ссылкой: пустая ссылка проверяется сравнением = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) и к NULL отношения не имеет.

Типы данных в ветках и типичные ограничения

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

Если нужен единый тип, приводите значения явно — например, функцией ВЫРАЗИТЬ:

ВЫБОР

КОГДА Док.Сумма > 0 ТОГДА ВЫРАЗИТЬ(Док.Сумма КАК ЧИСЛО(15, 2))

ИНАЧЕ 0

КОНЕЦ КАК Сумма

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

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

Пошаговая проверка запроса в консоли

Прежде чем встраивать конструкцию в отчёт или код, проверьте её в консоли запросов (встроенной в конфигуратор через временную обработку или внешней консоли запросов). Порядок действий простой, но экономит много времени на отладке.

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

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

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

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

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

Каждая строка попала в ожидаемую ветку, пустых значений нет

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

Часть строк содержит NULL или неверную категорию

Тип поля результата
Норма

Один тип во всех строках (число, строка, ссылка)

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

Смешанные типы, ошибка при группировке или выводе в СКД

Строки из левого соединения
Норма

NULL заменён значением по умолчанию через ЕСТЬ NULL или ЕСТЬNULL

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

Пустые значения там, где ожидались нули или текст

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

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

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

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

ВЫБОР КОГДА ТОГДА

Подходит для 2–10 условий по полям запроса; при большем числе веток становится трудно сопровождать

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

Идеален для замены NULL одним значением; не умеет сложных условий

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

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

Постобработка в коде

Гибкость без ограничений, но ломает СКД, динамические списки и пагинацию больших выборок

Частые вопросы по конструкции ВЫБОР

Можно ли использовать ВЫБОР в условии ГДЕ?

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

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

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

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

Ветки ТОГДА и ИНАЧЕ возвращают значения несовместимых типов — например, строку и ссылку на документ. Приведите значения к одному типу через ВЫРАЗИТЬ или замените одну из веток на значение совместимого типа.

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

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

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

Да, конструкция полностью поддерживается в произвольных запросах динамических списков и в наборах данных СКД. Учтите только, что произвольный запрос в динамическом списке ограничивает стандартные возможности интерактивного изменения данных, а для СКД важно, чтобы вычисляемое поле имело однозначный тип.

Как сравнить поле с пустой ссылкой внутри ВЫБОР?

Через ЗНАЧЕНИЕ с указанием пустой ссылки конкретного типа: КОГДА Док.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) ТОГДА "Не указан". Не путайте пустую ссылку с NULL — это разные состояния, и проверяются они по-разному.

Итог

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

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