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