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