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

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

Конструкция ВЫБОР КОГДА ТОГДА в языке запросов 1С

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

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

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

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

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

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

ВЫБОР

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

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

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

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

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

КОНЕЦ КАК КатегорияСделки

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

В условии КОГДА допустимы сравнения (=, <>, >, <, >=, <=), логические связки И, ИЛИ, НЕ, проверки В, ПОДОБНО, ЕСТЬ NULL и ссылки на перечисления через ЗНАЧЕНИЕ(...). Нельзя использовать вложенные запросы в условии — для этого применяют соединения или временные таблицы.

Простые условия: статусы и категории

Самый частый сценарий — заменить служебное значение понятным текстом. Например, вывести вид номенклатуры словами:

ВЫБРАТЬ

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

ВЫБОР

КОГДА Номенклатура.ТипНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ТипыНоменклатуры.Товар)

ТОГДА "Товар"

КОГДА Номенклатура.ТипНоменклатуры = ЗНАЧЕНИЕ(Перечисление.ТипыНоменклатуры.Услуга)

ТОГДА "Услуга"

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

КОНЕЦ КАК ТипСтрокой

ИЗ

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

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

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

ВЫБОР

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

ТОГДА 0

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

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

Вычисляемые значения и вложенные конструкции

В ветках ТОГДА и ИНАЧЕ можно писать не только литералы, но и выражения: арифметику, функции, обращения к полям. Например, расчёт цены со скидкой в зависимости от объёма:

ВЫБОР

КОГДА Продажи.Количество >= 100

ТОГДА Продажи.Цена * 0.9

КОГДА Продажи.Количество >= 10

ТОГДА Продажи.Цена * 0.95

ИНАЧЕ Продажи.Цена

КОНЕЦ КАК ИтоговаяЦена

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

ВЫБОР в условиях, группировках и итогах

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

ВЫБРАТЬ

Обороты.Счет,

СУММА(ВЫБОР

КОГДА Обороты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)

ТОГДА Обороты.Количество

ИНАЧЕ -Обороты.Количество

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

ИЗ

РегистрНакопления.ТоварыНаСкладах.Обороты КАК Обороты

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

Обороты.Счет

Приём «СУММА(ВЫБОР ...)» — стандартный способ развернуть строки в колонки: например, посчитать отдельно суммы по двум типам документов в одном запросе вместо двух соединений. Это часто работает быстрее, чем объединение двух выборок, потому что таблица читается один раз.

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

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

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

Когда число веток велико (десятки соответствий «значение → подстановка»), лучше создать временную таблицу соответствий из таблицы значений и соединиться с ней. Это проще сопровождать: список соответствий редактируется в коде как обычная таблица, а не как гигантская конструкция в тексте запроса.

Чем заменить ВЫБОР

ЕСТЬNULL(Поле, Значение)

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

Временная таблица соответствий + соединение

Подходит при большом числе пар «значение → результат». Требует подготовки таблицы в коде, зато легко сопровождается.

Несколько запросов с объединением

Подходит, когда ветки возвращают разнородные наборы полей. Увеличивает число обращений к данным, обычно медленнее.

Типичные ошибки и ограничения

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

Вторая ошибка — сравнение с перечислением через строку. Запись КОГДА Документ.Статус = "Проведен" не сработает, потому что статус — это ссылка на перечисление, а не строка. Правильно: КОГДА Документ.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыДокументов.Проведен). Аналогично с предопределёнными элементами справочников — только через ЗНАЧЕНИЕ(...) или параметр.

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

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

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

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

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

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

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

Строки в ветке ИНАЧЕ
Норма

Попадают только редкие нестандартные случаи

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

Большинство строк ушло в ИНАЧЕ — условия не покрывают данные

Значения NULL в итоговом поле
Норма

NULL отсутствуют

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

Есть NULL — забыта ветка ИНАЧЕ или условие не учитывает NULL

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

Один тип во всех строках, группировка и итоги работают

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

Смешанные типы — ошибки при дальнейшей обработке

Часто задаваемые вопросы

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

Технически да, но почти всегда это плохая идея. Условие через ВЫБОР мешает оптимизатору использовать индексы и ухудшает читаемость. Прямое условие с И/ИЛИ работает быстрее и понятнее.

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

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

Сколько веток КОГДА можно написать?

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

Почему условие КОГДА Поле = "Значение" не срабатывает?

Скорее всего, поле — ссылочного типа (перечисление, справочник), а сравнивается со строкой. Используйте ЗНАЧЕНИЕ(Перечисление.Имя.Значение) или передайте ссылку через параметр запроса.

Можно ли в ТОГДА вернуть результат другого запроса?

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

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

Поле получит значение NULL. Это частый источник ошибок: NULL не равен ничему, даже другому NULL, и ломает сравнения, арифметику и группировки. Всегда добавляйте ИНАЧЕ.

Итог

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

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