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