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