Разработка и Конфигурация · 11 мин
Конструкция ВЫБОР КОГДА ИНАЧЕ в запросах 1С: синтаксис и примеры
Как использовать конструкцию ВЫБОР КОГДА ТОГДА ИНАЧЕ КОНЕЦ в запросах 1С: синтаксис, примеры, сравнение типов, типичные ошибки и ограничения.
Конструкция ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ — аналог оператора CASE в языке запросов 1С. Она позволяет вернуть в поле выборки разные значения в зависимости от условий, не прибегая к соединениям нескольких запросов и не вынося логику в постобработку результата. Это один из самых востребованных приёмов при разработке отчётов и механизмов обмена.
Типичные сценарии: подмена NULL значением по умолчанию, расшифровка числового статуса в читаемую строку, выбор цены из разных источников по приоритету, группировка сумм по признаку операции. Во всех этих случаях одна конструкция ВЫБОР заменяет дополнительный цикл обхода выборки.
Ниже разобраны полный синтаксис, правила совместимости типов, работа с NULL, ограничения платформы и ошибки, которые чаще всего приводят к неверным данным или падению запроса.
Синтаксис конструкции ВЫБОР КОГДА ИНАЧЕ
Базовая форма выглядит так:
ВЫБРАТЬ
ВЫБОР
КОГДА Продажи.Сумма >= 100000
ТОГДА "Крупная"
КОГДА Продажи.Сумма >= 10000
ТОГДА "Средняя"
ИНАЧЕ "Мелкая"
КОНЕЦ КАК Категория
ИЗ
Документ.РеализацияТоваровУслуг КАК Продажи
Условия проверяются сверху вниз, и выполняется только первая подошедшая ветка КОГДА. Это важно: если переставить условия местами и поставить менее строгое выше, более строгое никогда не сработает. В примере выше проверка «больше 10000» не должна стоять раньше «больше 100000», иначе категория «Крупная» никогда не появится.
Конструкцию можно использовать не только в списке полей, но и в условии ГДЕ, в итогах и даже внутри агрегатных функций. Например, СУММА(ВЫБОР КОГДА ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход) ТОГДА Количество ИНАЧЕ 0 КОНЕЦ) — классический способ посчитать приход и расход в одном запросе.
Две формы записи: поисковая и простая
Первая форма — поисковая, с полным логическим выражением в каждом КОГДА (как в примере выше). Она универсальна и используется чаще всего, потому что условия могут быть любыми, включая сравнения разных полей и вызовы функций.
Вторая форма — простая: после ВЫБОР указывается выражение, а в КОГДА — значения для сравнения на равенство:
ВЫБОР Документ.ВидОперации
КОГДА ЗНАЧЕНИЕ(Перечисление.ВидыОпераций.Продажа)
ТОГДА "Реализация"
КОГДА ЗНАЧЕНИЕ(Перечисление.ВидыОпераций.Возврат)
ТОГДА "Возврат"
ИНАЧЕ "Прочее"
КОНЕЦ
Простая форма короче и читается легче, когда проверяется равенство одного поля нескольким значениям. Но она не поддерживает неравенства, диапазоны и составные условия — для них нужна поисковая форма.
Какую форму выбрать
Подходит для сравнения одного поля с фиксированными значениями: статусы, виды операций, перечисления. Не работает с диапазонами и неравенствами.
Универсальный вариант: любые логические выражения, сравнения нескольких полей, проверки на NULL. Чуть многословнее, но покрывает все сценарии.
Работа с NULL и типичный сценарий ЕСТЬ NULL
Самая частая причина применения ВЫБОР — замена NULL, который появляется при левом соединении, если в присоединённой таблице не нашлось записи. NULL нельзя сравнивать обычным равенством и нельзя выводить пользователю: в отчёте он отобразится пустотой, а арифметика с NULL даст NULL.
Классический приём с функцией ЕСТЬNULL короче и предпочтительнее:
ВЫБРАТЬ
Товары.Ссылка,
ЕСТЬNULL(Остатки.Количество, 0) КАК Остаток
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ПО Товары.Ссылка = Остатки.Номенклатура
ВЫБОР с проверкой КОГДА Остатки.Количество ЕСТЬ NULL ТОГДА 0 ИНАЧЕ Остатки.Количество КОНЕЦ делает то же самое, но длиннее. Используйте ВЫБОР там, где логика сложнее простой подмены NULL: например, когда по разным условиям нужно подставить разные значения по умолчанию.
Совместимость типов в ветках ТОГДА и ИНАЧЕ
Все значения, возвращаемые ветками ТОГДА и ИНАЧЕ, должны быть совместимы по типу: платформа формирует для поля выборки единый составной тип. Строки разной длины допустимы — тип станет строковым, но смешивать строку и ссылку на справочник в разных ветках нельзя: запрос выполнится, однако дальнейшая работа с таким полем (соединения, сравнения, сортировка) может дать неожиданные результаты или ошибку при выгрузке.
Особое внимание — к числам. Если в одной ветке возвращается целое, а в другой дробное значение, тип поля будет числовым с достаточной точностью, но при выводе в СКД или таблицу значений могут проявиться особенности форматирования. Явно приводите значения к одному виду, например через ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 2)).
Если нужно вернуть ссылку на разные справочники в зависимости от условия — это допустимо, поле получит составной ссылочный тип. Но помните, что по такому полю нельзя строить соединение без уточнения конкретной таблицы.
ВЫБОР в условиях, итогах и агрегатных функциях
В секции ГДЕ конструкция ВЫБОР применяется, когда критерий отбора зависит от данных самой строки. Например, отобрать документы, у которых контрольное значение сравнивается с разными полями в зависимости от вида операции. Такое условие корректно работает, но мешает оптимизатору использовать индексы — на больших таблицах фильтрация с ВЫБОР в ГДЕ может быть заметно медленнее, чем простое сравнение.
Внутри агрегатных функций ВЫБОР — основной инструмент сводных отчётов. Суммы прихода и расхода, количество документов по статусам, выручка по признаку возврата — всё это считается одним проходом:
ВЫБРАТЬ
Обороты.Номенклатура,
СУММА(ВЫБОР КОГДА Обороты.КоличествоОборот > 0
ТОГДА Обороты.КоличествоОборот ИНАЧЕ 0 КОНЕЦ) КАК Продано,
СУММА(ВЫБОР КОГДА Обороты.КоличествоОборот < 0
ТОГДА -Обороты.КоличествоОборот ИНАЧЕ 0 КОНЕЦ) КАК Возвращено
ИЗ
РегистрНакопления.Продажи.Обороты КАК Обороты
СГРУППИРОВАТЬ ПО
Обороты.Номенклатура
В секции ИТОГИ и в ресурсах СКД ВЫБОР тоже допустим, но логику лучше держать в основном запросе: так проще отлаживать и проверять промежуточный результат в консоли запросов.
Перед тем как встраивать сложный ВЫБОР в боевой запрос, проверьте его отдельно в консоли запросов на небольшой выборке: выведите исходное поле и результат ВЫБОР рядом. Так сразу видно, сработали ли все ветки и не появились ли неожиданные NULL.
Ограничения и производительность
ВЫБОР — вычисляемое выражение, и оно выполняется для каждой строки результата. На выборках в сотни тысяч записей несколько вложенных конструкций заметно увеличивают время выполнения. Если одно и то же условие повторяется в нескольких полях, имеет смысл вынести его во временную таблицу и переиспользовать.
Вложенные ВЫБОР внутри ВЫБОР допустимы синтаксически, но уже два-три уровня вложенности делают запрос трудным для чтения и отладки. Альтернатива — разбить логику на несколько полей или перенести её в СКД с вычисляемыми полями, где выражения пишутся на встроенном языке.
Ещё одно ограничение: внутри КОГДА нельзя использовать агрегатные функции без группировки и нельзя ссылаться на поля, не входящие в группировку, если конструкция стоит после СГРУППИРОВАТЬ ПО. Ошибки такого рода платформа сообщает на этапе выполнения запроса, а не при написании.
Как выбрать действие
Как проверить корректность результата
После написания запроса убедитесь, что каждая ветка ВЫБОР реально срабатывает. Самый надёжный способ — вывести рядом исходное поле и результат конструкции и проконтролировать несколько строк с разными значениями условий.
Проверьте граничные случаи: значение ровно на границе диапазона, NULL в исходном поле, пустая ссылка. Именно на границах чаще всего обнаруживается неправильный порядок КОГДА или забытое ИНАЧЕ.
Если конструкция используется в агрегатах, сверьте итоговые суммы с контрольным запросом без ВЫБОР — суммы по группам должны сойтись. Расхождение означает, что часть строк попала не в ту ветку или потерялась из-за NULL.
Как проверить результат
В тестовой выборке встречаются значения из каждой ветки ТОГДА и ИНАЧЕ
Какая-то ветка не появляется ни разу — вероятно, нарушен порядок КОГДА
Поле заполнено во всех строках
Есть NULL — не хватает ветки ИНАЧЕ или условие проверяет NULL через равенство
Сумма по полю с ВЫБОР совпадает с контрольным запросом без него
Расхождение — часть строк попала не в ту ветку
Частые вопросы
Обязательна ли ветка ИНАЧЕ в конструкции ВЫБОР?
Синтаксически — нет, запрос выполнится и без неё. Но если ни одно условие КОГДА не выполнится, поле получит значение NULL, что создаёт проблемы при сортировке, группировке и выводе. Практическое правило: ИНАЧЕ писать всегда, хотя бы со значением NULL — тогда поведение явное и осознанное.
Чем ВЫБОР отличается от функции ЕСТЬNULL?
ЕСТЬNULL решает одну задачу — замену NULL конкретным значением. ВЫБОР универсальнее: проверяет любые условия и возвращает разные значения по веткам. Для простой подмены NULL используйте ЕСТЬNULL, для условной логики — ВЫБОР.
Можно ли использовать ВЫБОР в секции ГДЕ?
Да, конструкция допустима в условиях отбора. Но учтите, что вычисляемое условие не использует индексы, поэтому на больших таблицах отбор с ВЫБОР может работать медленнее простого сравнения поля. По возможности выносите фильтрацию в параметры виртуальных таблиц.
Почему ветка КОГДА с условием «поле = NULL» не срабатывает?
Потому что NULL не равен ничему, включая сам себя: любое сравнение с NULL даёт ложь. Проверку нужно писать как «поле ЕСТЬ NULL», а для подстановки значения по умолчанию удобнее функция ЕСТЬNULL.
Можно ли вкладывать один ВЫБОР в другой?
Да, вложенность допустима и в ТОГДА, и в ИНАЧЕ. Однако больше двух уровней вложенности делают запрос трудночитаемым. При сложной логике лучше разбить её на несколько полей или перенести в вычисляемые поля СКД.
Работает ли ВЫБОР внутри СУММА и других агрегатных функций?
Да, это один из основных приёмов: СУММА(ВЫБОР КОГДА условие ТОГДА значение ИНАЧЕ 0 КОНЕЦ) позволяет посчитать несколько разных итогов за один проход по таблице. Главное — чтобы в ветке ИНАЧЕ стоял 0, а не NULL, иначе строки без условия исказят сумму.
Что важно запомнить
ВЫБОР КОГДА ТОГДА ИНАЧЕ КОНЕЦ — стандартный способ условной логики в запросах 1С. Пишите ИНАЧЕ всегда, следите за порядком условий и совместимостью типов, для подмены NULL используйте ЕСТЬNULL, а сложную многоуровневую логику выносите в СКД или постобработку.