К статье
Практический материал

Разработка и Конфигурация · 11 мин

ВЫБОР КОГДА в запросе 1С: условная логика и приведение типов

Как использовать конструкцию ВЫБОР КОГДА в запросах 1С: синтаксис, примеры с ВЫРАЗИТЬ, сравнение с ЕСТЬNULL, типичные ошибки и способы проверки результата.

Конструкция ВЫБОР КОГДА — это аналог оператора CASE WHEN из классического SQL, встроенный в язык запросов 1С. Она позволяет вычислять значение поля по условию прямо в запросе: подставлять текстовые расшифровки статусов, рассчитывать скидки по диапазонам, заменять NULL и приводить данные к нужному виду без постобработки в коде.

Часто вместе с ВЫБОР используется функция ВЫРАЗИТЬ — она приводит значение к конкретному типу. Это нужно, когда ветки условия возвращают разные типы данных или когда поле составного типа требуется сузить до одного ссылочного типа для соединения таблиц. Связка «ВЫБОР КОГДА + ВЫРАЗИТЬ» — один из самых востребованных приёмов при разработке отчётов и сложных выборок.

Ниже разобран синтаксис обеих конструкций, практические сценарии применения, ограничения платформы и типичные ошибки, из-за которых запрос либо падает с ошибкой, либо возвращает неожиданный результат.

Синтаксис конструкции ВЫБОР КОГДА

Полная форма конструкции выглядит так:

ВЫБОР

КОГДА Условие1 ТОГДА Значение1

КОГДА Условие2 ТОГДА Значение2

ИНАЧЕ ЗначениеПоУмолчанию

КОНЕЦ

Условия проверяются сверху вниз, и срабатывает первая истинная ветка. Если ни одно условие не выполнилось, возвращается значение из ИНАЧЕ. Ветка ИНАЧЕ необязательна, но без неё при несовпадении всех условий поле получит значение NULL — это частая причина «пустых» колонок в отчётах.

Конструкцию можно использовать в списке выбираемых полей, в условии ГДЕ, в ИМЕЮЩИЕ и даже в УПОРЯДОЧИТЬ ПО. На практике чаще всего она встречается именно в списке полей выборки.

ВЫБРАТЬ

Заказы.Номер,

ВЫБОР

КОГДА Заказы.Сумма >= 100000 ТОГДА "Крупный"

КОГДА Заказы.Сумма >= 10000 ТОГДА "Средний"

ИНАЧЕ "Мелкий"

КОНЕЦ КАК КатегорияЗаказа

ИЗ

Документ.ЗаказПокупателя КАК Заказы

Когда нужна функция ВЫРАЗИТЬ

Функция ВЫРАЗИТЬ(Значение КАК Тип) выполняет две задачи. Первая — приведение значения к конкретному типу данных: строке заданной длины, числу с нужной точностью, дате, булево или ссылочному типу. Вторая — сужение составного типа поля до одного ссылочного типа, что необходимо для соединений и обращения к реквизитам через точку.

Классическая ситуация: поле Регистратор у регистра накопления имеет составной тип (несколько видов документов). Обратиться к реквизиту конкретного документа напрямую нельзя — сначала поле нужно выразить как нужный тип:

ВЫБРАТЬ

ВЫРАЗИТЬ(Продажи.Регистратор КАК Документ.РеализацияТоваровУслуг).Склад КАК Склад

ИЗ

РегистрНакопления.Продажи КАК Продажи

ГДЕ

Продажи.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг

Ещё одно применение — усечение строк. Если соединяются таблицы по строковому полю неограниченной длины, платформа может не использовать индекс, и запрос резко замедлится. Приведение к строке фиксированной длины через ВЫРАЗИТЬ(Поле КАК Строка(100)) решает проблему.

Совместное использование ВЫБОР и ВЫРАЗИТЬ

Главное правило: все ветки ВЫБОР должны возвращать значения одного типа. Если в одной ветке возвращается ссылка на справочник «Номенклатура», а в другой — на «Контрагенты», итоговое поле получит составной тип, что осложнит дальнейшую работу с запросом. Чтобы управлять типом результата, значения в ветках оборачивают в ВЫРАЗИТЬ.

Типичный пример — формирование поля с условным представлением контрагента из разных источников:

ВЫБРАТЬ

ВЫБОР

КОГДА Док.Контрагент ЕСТЬ NULL

ТОГДА ВЫРАЗИТЬ("Не указан" КАК Строка(50))

ИНАЧЕ ВЫРАЗИТЬ(Док.Контрагент.Наименование КАК Строка(50))

КОНЕЦ КАК КонтрагентПредставление

ИЗ

Документ.РеализацияТоваровУслуг КАК Док

Здесь ВЫРАЗИТЬ гарантирует, что обе ветки вернут строку одинаковой длины. Без приведения ветка с Наименование вернула бы строку той длины, которая задана в метаданных справочника, а литерал — строку своей длины, и тип поля стал бы неоднозначным.

Обратный сценарий — выражение результата ВЫБОР целиком:

ВЫРАЗИТЬ(ВЫБОР

КОГДА Т.ТипЦены = &Розничная ТОГДА Т.Цена * 1.2

ИНАЧЕ Т.Цена

КОНЕЦ КАК Число(15,2)) КАК ЦенаИтог

1c
ВЫБОР
    КОГДА Продажи.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
        ТОГДА ВЫРАЗИТЬ(Продажи.Регистратор КАК Документ.РеализацияТоваровУслуг).Склад
    ИНАЧЕ NULL
КОНЕЦ КАК Склад

Практические сценарии применения

Расшифровка перечислений и статусов

Перечисления в запросе сравниваются со значениями через ЗНАЧЕНИЕ(Перечисление.Вид.Имя). С помощью ВЫБОР удобно выводить человекочитаемый статус вместо ссылки:

ВЫБОР

КОГДА Заказ.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказа.Новый) ТОГДА "Новый"

КОГДА Заказ.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказа.Отгружен) ТОГДА "Отгружен"

ИНАЧЕ "Прочее"

КОНЕЦ КАК СтатусТекст

Замена NULL осмысленным значением

Для простой замены NULL короче использовать ЕСТЬNULL(Поле, Значение). Но если замена зависит от условия — например, для разных видов документов подставляются разные значения — нужен ВЫБОР:

ВЫБОР

КОГДА Т.Склад ЕСТЬ NULL И Т.ВидОперации = &Розница ТОГДА &СкладРозницы

КОГДА Т.Склад ЕСТЬ NULL ТОГДА &СкладПоУмолчанию

ИНАЧЕ Т.Склад

КОНЕЦ КАК Склад

Группировка по вычисляемому признаку

ВЫБОР можно использовать в итогах и группировках, например чтобы агрегировать продажи по ценовым сегментам. Поле с конструкцией ВЫБОР включается в СГРУППИРОВАТЬ ПО, а суммы считаются агрегатной функцией СУММА.

ВЫБОР или ЕСТЬNULL

ЕСТЬNULL(Поле, Значение)

Подходит только для замены NULL конкретным значением. Короче и читается проще.

ВЫБОР КОГДА

Нужен, когда условий несколько, замена зависит от логики или ветки возвращают вычисляемые выражения.

Ограничения и влияние на производительность

Конструкция ВЫБОР вычисляется для каждой строки результата. На больших выборках сложные вложенные условия увеличивают время выполнения запроса, особенно если внутри условий используются обращения к реквизитам через точку — каждое такое обращение может порождать неявное соединение.

Опасный приём — вложенные ВЫБОР внутри ВЫБОР с глубиной больше двух-трёх уровней. Такой запрос трудно читать и отлаживать. Если логика разветвлённая, лучше вынести её во временную таблицу с заранее подготовленными признаками или вынести часть условий в параметры запроса.

Ещё одно ограничение: ВЫРАЗИТЬ по ссылочному типу не проверяет корректность данных. Если в составном поле лежит ссылка другого вида, результатом будет NULL, и соединение с этой строкой пропадёт. Поэтому фильтр ГДЕ Поле ССЫЛКА Документ.НужныйВид должен идти до приведения или вместе с ним.

Типичные ошибки и как их проверить

Первая ошибка — отсутствие ветки ИНАЧЕ. Запрос выполняется без сообщений, но часть строк получает NULL в вычисляемой колонке, и отчёт выглядит «дырявым». Признак: в результате запроса в нужной колонке встречаются пустые значения там, где их быть не должно.

Вторая ошибка — несовпадение типов веток. Например, в одной ветке число, в другой строка. Платформа в ряде случаев допустит такой запрос, но итоговый тип поля станет составным, и сортировка или группировка по нему даст неожиданный результат. Лечится приведением веток через ВЫРАЗИТЬ к одному типу.

Третья ошибка — сравнение с NULL через знак равенства внутри условия КОГДА. Выражение КОГДА Поле = NULL никогда не истинно; корректно писать КОГДА Поле ЕСТЬ NULL.

Типичные ошибки
01
Нет ветки ИНАЧЕ — часть строк получает NULL в вычисляемом поле
02
Сравнение с NULL через «=» вместо ЕСТЬ NULL — условие никогда не срабатывает
03
Разные типы значений в ветках КОГДА — составной тип результата и ошибки при группировке
04
ВЫРАЗИТЬ без фильтра ССЫЛКА — строки с другими типами ссылок превращаются в NULL
05
Глубокая вложенность ВЫБОР в ВЫБОР — запрос трудно читать и отлаживать

Для проверки результата удобно выполнить запрос в консоли запросов и просмотреть выборку глазами: убедиться, что каждая ветка условия реально срабатывает хотя бы на одной строке тестовых данных. Если тестовых данных под какую-то ветку нет — её корректность остаётся неподтверждённой.

Контрольные точки

Как проверить результат

Значения вычисляемой колонки
Норма

Каждая строка содержит осмысленное значение одной из веток

Тревожный признак

Встречаются пустые значения (NULL) там, где их не должно быть

Тип поля результата
Норма

Единый тип, соединения и группировки работают

Тревожный признак

Составной тип, сортировка или группировка ведут себя странно

Работа каждой ветки
Норма

Для каждого КОГДА есть тестовая строка, где ветка срабатывает

Тревожный признак

Часть условий не покрыта данными — поведение не проверено

Порядок действий при написании запроса с ВЫБОР

Работать с конструкцией удобно по простому алгоритму: сначала сформулировать все условия словами, затем перенести их в запрос, затем проверить типы и результат на реальных данных.

Порядок действий
  1. 1
    Выпишите все условия и значения для каждой ветки, включая значение по умолчанию для ИНАЧЕ
  2. 2
    Напишите конструкцию ВЫБОР в списке полей и задайте псевдоним через КАК
  3. 3
    Выровняйте типы веток через ВЫРАЗИТЬ, если значения разнотипные
  4. 4
    Добавьте фильтр ССЫЛКА, если приводите составное поле к конкретному типу
  5. 5
    Выполните запрос в консоли и убедитесь, что каждая ветка срабатывает и NULL нет в неожиданных местах
Итог

Что важно запомнить

ВЫБОР КОГДА вычисляет значение по условиям внутри запроса, ВЫРАЗИТЬ приводит значение к нужному типу. Всегда добавляйте ИНАЧЕ, выравнивайте типы веток и проверяйте запрос на данных, покрывающих все условия.

Частые вопросы

Чем ВЫБОР отличается от ЕСТЬNULL?

ЕСТЬNULL — частный случай: она заменяет NULL заданным значением и принимает ровно два аргумента. ВЫБОР поддерживает любое количество условий и произвольные выражения в ветках. Если задача — только подставить значение вместо NULL, ЕСТЬNULL короче и понятнее.

Можно ли использовать ВЫБОР в условии ГДЕ?

Да, конструкция допустима в ГДЕ, ИМЕЮЩИЕ и УПОРЯДОЧИТЬ ПО. Однако фильтрацию лучше по возможности выполнять прямыми условиями на поля таблиц: так СУБД сможет использовать индексы, а запрос выполнится быстрее.

Почему после ВЫРАЗИТЬ поле стало пустым?

Значение не приводится к указанному типу: например, в составном поле лежит ссылка другого вида документа. В этом случае результат — NULL без сообщения об ошибке. Добавьте условие Поле ССЫЛКА НужныйТип, чтобы отфильтровать или явно обработать такие строки.

Есть ли ограничение на количество веток КОГДА?

Жёсткого документированного ограничения на число веток нет, но при большом количестве условий запрос становится трудно читаемым и медленнее выполняется. При десятках вариантов лучше создать временную таблицу соответствий и соединиться с ней.

Можно ли вкладывать ВЫБОР внутрь ВЫБОР?

Да, вложенность поддерживается и в ветках ТОГДА, и в условиях КОГДА. Практический предел — два-три уровня: глубже конструкцию почти невозможно отлаживать, и лучше перенести часть логики во временные таблицы или параметры.

Как сравнить поле с перечислением внутри КОГДА?

Через функцию ЗНАЧЕНИЕ: КОГДА Док.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказа.Отгружен). Сравнивать ссылку на перечисление со строкой нельзя — условие просто не сработает, а в некоторых случаях запрос завершится ошибкой несоответствия типов.