Разработка и Конфигурация · 10 мин
Конструкция ВЫБОР КОГДА ТОГДА в запросах 1С
Как использовать конструкцию ВЫБОР КОГДА ТОГДА ИНАЧЕ КОНЕЦ в запросах 1С: синтаксис, примеры, типичные ошибки, сравнение с ЕСТЬNULL и проверка результата.
Конструкция ВЫБОР ... КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ — это аналог оператора CASE в классическом SQL, реализованный в языке запросов 1С. Она позволяет вычислять значение поля по условию прямо в запросе, не выгружая данные для постобработки в коде. Это один из самых востребованных приёмов при построении отчётов, динамических списков и выборок, где значение колонки зависит от условий.
Типовые задачи, которые решает эта конструкция: подстановка текстового статуса вместо числового кода, расчёт скидки по диапазону суммы, замена NULL понятным значением, группировка данных по вычисляемым категориям. Во всех этих случаях логика выполняется на уровне СУБД, что быстрее и чище, чем обход выборки в цикле.
Ниже разобран полный синтаксис, рабочие примеры, ограничения по типам данных, сравнение с альтернативами и типичные ошибки, из-за которых запрос падает с ошибкой или возвращает неожиданный результат.
Синтаксис конструкции ВЫБОР КОГДА ТОГДА
Полная форма конструкции выглядит так:
ВЫБОР
КОГДА <Условие1>
ТОГДА <Значение1>
КОГДА <Условие2>
ТОГДА <Значение2>
ИНАЧЕ <ЗначениеПоУмолчанию>
КОНЕЦ
Условия проверяются последовательно сверху вниз. Как только первое условие оказывается истинным, возвращается соответствующее значение, а остальные ветки не вычисляются. Если ни одно условие не сработало, возвращается значение из ИНАЧЕ; если ветки ИНАЧЕ нет — возвращается NULL.
Условия в КОГДА — это обычные логические выражения языка запросов: сравнения, И, ИЛИ, НЕ, В, МЕЖДУ, ПОДОБНО, проверка ЕСТЬ NULL. Значения после ТОГДА могут быть литералами, полями, параметрами, выражениями и даже вложенными конструкциями ВЫБОР.
Простые примеры использования
Подстановка текстового статуса вместо кода
Частая задача — показать пользователю понятный статус вместо служебного значения. Например, в динамическом списке или отчёте:
ВЫБРАТЬ
Заказы.Номер КАК Номер,
ВЫБОР
КОГДА Заказы.Проведен
ТОГДА "Проведён"
КОГДА Заказы.ПометкаУдаления
ТОГДА "Помечен на удаление"
ИНАЧЕ "Черновик"
КОНЕЦ КАК Состояние
ИЗ
Документ.ЗаказПокупателя КАК Заказы
Обратите внимание на порядок условий: если документ одновременно проведён и помечен на удаление, сработает первая ветка. Порядок КОГДА имеет значение — более специфичные условия ставьте выше.
Расчёт значения по диапазону
Второй классический сценарий — вычисление величины по интервалам, например процента скидки:
ВЫБОР
КОГДА Продажи.Сумма >= 100000
ТОГДА Продажи.Сумма * 0.1
КОГДА Продажи.Сумма >= 50000
ТОГДА Продажи.Сумма * 0.05
ИНАЧЕ 0
КОНЕЦ КАК Скидка
Здесь важно, что диапазоны проверяются сверху вниз: сначала самое «сильное» условие. Если поменять ветки местами, сумма 120 000 попадёт в ветку «от 50 000», и скидка будет рассчитана неверно.
ВЫБОР
КОГДА Товары.Количество = 0
ТОГДА "Нет на складе"
КОГДА Товары.Количество < 10
ТОГДА "Заканчивается"
ИНАЧЕ "В наличии"
КОНЕЦ КАК ОстатокТекстПравила совместимости типов в ветках
Главное ограничение конструкции: все значения, возвращаемые ветвями ТОГДА и ИНАЧЕ, должны иметь совместимые типы. Если одна ветка возвращает строку, а другая — число, конструктор запроса и платформа могут выдать ошибку либо привести значения к неожиданному виду в зависимости от СУБД.
Особенно коварна ситуация со строками разной длины: если в одной ветке литерал «короткий», а в другой — длинный текст, тип поля результата определяется платформой, и в некоторых случаях значение может обрезаться. Чтобы избежать этого, явно приводите результат через ВЫРАЗИТЬ(... КАК Строка(200)).
Также осторожно смешивайте ссылочные типы. Ветка, возвращающая ссылку на справочник «Номенклатура», и ветка, возвращающая ссылку на «Контрагенты», дадут поле составного типа — это допустимо, но усложняет дальнейшую обработку и может замедлить запрос.
ВЫБОР в сочетании с группировкой и итогами
Конструкцию можно использовать не только в списке полей, но и внутри агрегатных функций — это мощный приём для сводных отчётов. Например, суммирование только проведённых документов:
ВЫБРАТЬ
Продажи.Контрагент КАК Контрагент,
СУММА(ВЫБОР
КОГДА Продажи.Проведен
ТОГДА Продажи.Сумма
ИНАЧЕ 0
КОНЕЦ) КАК СуммаПроведенных,
СУММА(ВЫБОР
КОГДА НЕ Продажи.Проведен
ТОГДА Продажи.Сумма
ИНАЧЕ 0
КОНЕЦ) КАК СуммаЧерновиков
ИЗ
Документ.РеализацияТоваровУслуг КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Контрагент
Такой подход заменяет два отдельных запроса с отборами и последующее объединение результатов в коде. Однако помните: ВЫБОР нельзя использовать непосредственно в предложении ИМЕЮЩИЕ без агрегатной функции — там допустимы только агрегаты и поля группировки.
ВЫБОР против ЕСТЬNULL и других альтернатив
Часто одну и ту же задачу можно решить разными средствами. Выбор зависит от сути условия:
| Инструмент | Когда применять | Ограничение |
|---|---|---|
| ВЫБОР КОГДА ТОГДА | Несколько условий, диапазоны, сложная логика | Громоздкий для простой замены NULL |
| ЕСТЬNULL(Поле, Значение) | Только замена NULL на значение по умолчанию | Не работает с произвольными условиями |
| Значение(Перечисление...) | Подстановка конкретного значения перечисления или предопределённого элемента | Это не условие, а литерал |
| Обработка в коде после запроса | Логика зависит от функций встроенного языка, недоступных в запросе | Медленнее, больше кода |
Простое правило: если условие сводится к «поле равно NULL — подставь другое значение», используйте ЕСТЬNULL — это короче и читабельнее. Если условий два и больше или они сложнее сравнения с NULL — берите ВЫБОР.
Сравнение вариантов
Подходит для любых условий и диапазонов; единственный вариант при нескольких ветках. Минус — многословный синтаксис.
Идеален для единственной задачи — замены NULL значением по умолчанию. Не умеет ничего другого.
Нужно, когда логика опирается на функции встроенного языка или обращение к другим данным. Медленнее и усложняет сопровождение.
Типичные ошибки и как их избежать
Первая и самая частая ошибка — пропущенная ветка ИНАЧЕ. Если ни одно условие не выполнилось, поле получит значение NULL, что ломает последующие сравнения, сортировку и вывод в отчёт. Всегда явно указывайте ИНАЧЕ, даже если уверены, что все случаи покрыты.
Вторая ошибка — неверный порядок условий. Условия проверяются сверху вниз, и первое сработавшее «забирает» строку. Общие условия, поставленные выше частных, перехватывают данные раньше времени.
Третья группа проблем — типы: смешение строк разной длины, чисел с разной точностью, ссылок разных видов. Проверяйте тип результата через конструктор запроса или пробный вывод. Четвёртая ошибка — использование ВЫБОР там, где достаточно ЕСТЬNULL или отбора в ГДЕ: это делает запрос тяжелее для чтения и оптимизации.
Проверка результата и отладка
Надёжный способ проверить конструкцию — выполнить запрос в консоли запросов на данных, которые гарантированно покрывают каждую ветку. Подготовьте по одному-два документа или элемента под каждое условие, включая «пограничные» значения диапазонов (ровно 50 000, ровно 100 000 в примере со скидкой).
Дополнительно полезно вывести рядом с вычисляемым полем исходные поля, участвующие в условии. Так сразу видно, в какую ветку попала каждая строка и почему. Если результат содержит NULL там, где его не должно быть, — почти наверняка отсутствует ветка ИНАЧЕ или условие не учитывает NULL в исходном поле (помните: любое сравнение с NULL даёт не ИСТИНУ, поэтому такие строки «проваливаются» мимо всех КОГДА).
Как проверить результат
Каждая строка получила ожидаемое значение своей ветки, NULL отсутствуют
Есть NULL или значения из «чужих» веток — проверяйте ИНАЧЕ и порядок условий
Граница попадает в задуманную ветку (например, ровно 50000 даёт скидку 5%)
Граница попадает не туда — пересмотрите знаки сравнения и порядок КОГДА
Тип единый, строки не обрезаны
Строки усечены или типы смешаны — добавьте ВЫРАЗИТЬ
FAQ
Можно ли вкладывать один ВЫБОР внутрь другого?
Да, вложенные конструкции допустимы: значение после ТОГДА или ИНАЧЕ может быть другим ВЫБОР. Практический совет — не уходить глубже двух уровней: такие запросы тяжело читать и отлаживать. При более сложной логике лучше разбить вычисления на временные таблицы или вынести часть в код.
Можно ли использовать ВЫБОР в секции ГДЕ?
Можно, но только как часть сравнения, например: ГДЕ ВЫБОР КОГДА ... КОНЕЦ = &Значение. Сам по себе ВЫБОР без сравнения в условии отбора не используется. Чаще всего в ГДЕ проще написать обычные логические условия с И/ИЛИ — это читабельнее и лучше оптимизируется СУБД.
Что вернёт ВЫБОР, если ни одно условие не выполнилось?
Если ветка ИНАЧЕ указана — её значение. Если ИНАЧЕ нет — NULL. Поэтому ИНАЧЕ рекомендуется писать всегда, даже со значением 0 или пустой строкой, чтобы избежать неожиданных NULL в результате.
Работает ли ВЫБОР в СКД и динамических списках?
Да, конструкция полностью поддерживается в текстах запросов наборов данных СКД и в произвольных запросах динамических списков. В СКД аналогичную логику иногда выносят в вычисляемые поля, но ВЫБОР в запросе обычно работает быстрее, так как выполняется на стороне СУБД.
Как ВЫБОР влияет на производительность запроса?
Сама конструкция вычисляется быстро и обычно не является узким местом. Замедление возможно, если ВЫБОР участвует в соединениях или отборах по вычисляемому значению — тогда СУБД не может использовать индексы. В таких случаях лучше отфильтровать данные до вычисления, например через временную таблицу.
Что важно запомнить
ВЫБОР КОГДА ТОГДА ИНАЧЕ КОНЕЦ — основной способ условных вычислений в запросах 1С. Условия проверяются сверху вниз, поэтому частные случаи ставьте выше общих. Всегда указывайте ИНАЧЕ, следите за совместимостью типов веток и для простой замены NULL предпочитайте ЕСТЬNULL. Проверяйте результат на данных, покрывающих все ветки, включая границы диапазонов.