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