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