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