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