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