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

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

Конструкция ВЫБОР КОГДА ТОГДА в запросах 1С: синтаксис и практика

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

Конструкция ВЫБОР КОГДА ТОГДА — это аналог условного оператора «если… то… иначе» внутри языка запросов 1С. Она позволяет вернуть разные значения в одном поле в зависимости от условия, не прибегая к нескольким запросам и без постобработки в коде. Типичные задачи: вывести текстовое представление статуса документа, подставить значение по умолчанию вместо NULL, разделить данные на категории для отчёта.

Конструкция полностью соответствует оператору CASE в стандарте SQL и компилируется платформой в него при передаче запроса в СУБД. Это значит, что вычисление происходит на стороне сервера базы данных, а не в памяти приложения, — производительность при корректном использовании не страдает. Ниже разобраны синтаксис, типовые сценарии, ограничения и ошибки, которые чаще всего встречаются на практике.

Синтаксис конструкции и базовый пример

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

ВЫБРАТЬ

Номенклатура.Ссылка КАК Товар,

ВЫБОР

КОГДА Остатки.КоличествоОстаток ЕСТЬ NULL

ТОГДА 0

КОГДА Остатки.КоличествоОстаток < 10

ТОГДА Остатки.КоличествоОстаток

ИНАЧЕ 10

КОНЕЦ КАК ОстатокДляЗаказа

ИЗ

Справочник.Номенклатура КАК Номенклатура

ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

ПО Номенклатура.Ссылка = Остатки.Номенклатура

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

Типовые сценарии использования

Самая частая задача — замена NULL на значение по умолчанию. При левом соединении с виртуальными таблицами остатков или оборотов отсутствующие записи дают NULL в числовых полях, и любые арифметические операции с ними тоже вернут NULL. Обёртка в ВЫБОР КОГДА … ЕСТЬ NULL ТОГДА 0 решает проблему, хотя функция ЕСТЬNULL() короче и предпочтительнее именно для этой цели.

Вторая типовая задача — категоризация данных для отчётов. Например, разбить контрагентов на группы по сумме долга, а документы — по статусу проведения. Текстовое представление при этом формируется прямо в запросе, и в коде остаётся только вывести результат.

ВЫБОР

КОГДА Долг.СуммаОстаток > 100000

ТОГДА "Критический"

КОГДА Долг.СуммаОстаток > 0

ТОГДА "Есть задолженность"

ИНАЧЕ "Долга нет"

КОНЕЦ КАК СтатусДолга

Третий сценарий — выбор источника значения. Например, взять цену из индивидуального договора, а если её нет — из общего прайса. Это позволяет реализовать каскадную логику «сначала приоритетный источник, потом резервный» одним полем запроса.

Составные условия и логические операторы

Внутри КОГДА допустимы любые логические выражения, которые разрешены в секции ГДЕ: сравнения, И, ИЛИ, НЕ, проверки В ИЕРАРХИИ, В списке значений, ПОДОБНО. Это позволяет строить сложные ветвления без вложенных конструкций ВЫБОР.

КОГДА Заказ.Проведен

И НЕ Заказ.ПометкаУдаления

И Заказ.СуммаДокумента > 0

ТОГДА "Активный"

При комбинировании И и ИЛИ используйте скобки явно — приоритет операторов в запросах тот же, что в обычной логике (И выше ИЛИ), но явная группировка защищает от ошибок при последующем редактировании запроса другими разработчиками.

Вложенные конструкции ВЫБОР

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

ВЫБОР

КОГДА Контрагент.ЮрФизЛицо = ЗНАЧЕНИЕ(Перечисление.ЮрФизЛицо.ЮрЛицо)

ТОГДА ВЫБОР

КОГДА Контрагент.ИНН = ""

ТОГДА "Юрлицо без ИНН"

ИНАЧЕ "Юрлицо"

КОНЕЦ

ИНАЧЕ "Физлицо"

КОНЕЦ КАК КатегорияКонтрагента

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

Типы данных в ветвях: требования и подводные камни

Все ветви ТОГДА и ИНАЧЕ должны возвращать значения совместимых типов. Смешивание строки и числа в одном поле приведёт либо к ошибке выполнения запроса, либо к неявному приведению с непредсказуемым результатом — поведение зависит от используемой СУБД. Платформа не всегда перехватывает такую ошибку на этапе проверки запроса в консоли.

Отдельная тонкость — строки разной длины. Если одна ветвь возвращает строку из реквизита с ограничением 10 символов, а другая — литерал длиннее, СУБД может обрезать результат до длины первой ветви. Надёжное решение — привести все строковые ветви к одному типу через ВЫРАЗИТЬ(… КАК Строка(150)).

Со ссылочными типами ситуация похожая: если одна ветвь возвращает ссылку на справочник «Номенклатура», а другая — на «Контрагенты», поле станет составного типа. Это допустимо, но замедляет работу с полем и запрещает использование его в соединениях без дополнительного приведения.

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

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

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

Конструкцию ВЫБОР нельзя использовать в параметрах виртуальных таблиц — там допустимы только простые условия сравнения. В секции ГДЕ и в условиях соединений ВЫБОР использовать можно, но делать этого не стоит: такие условия не используют индексы, и СУБД вынуждена сканировать таблицу целиком. Фильтрацию всегда лучше выражать прямыми условиями.

Альтернативы: ЕСТЬNULL и выбор в СКД

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

В отчётах на СКД часть логики ВЫБОР можно вынести в вычисляемые поля или выражения представления. Это уместно, когда ветвление нужно только для отображения, а сами данные в запросе остаются «сырыми». Однако если категория участвует в группировках и отборах, вычислять её надо именно в запросе, иначе СКД не сможет по ней сгруппировать.

Сравнение вариантов

ВЫБОР КОГДА ТОГДА

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

ЕСТЬNULL()

Только замена NULL значением по умолчанию. Короче и понятнее, но не умеет ничего другого

Вычисляемые поля СКД

Ветвление только для отображения в отчёте. Не подходит для группировок и отборов

Постобработка в коде

Крайний случай: логика слишком сложна для запроса. Замедляет обработку больших выборок

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

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

Особое внимание уделите строкам, где исходные поля содержат NULL, и граничным значениям — ровно на пороге условия сравнения. Именно там чаще всего обнаруживаются ошибки порядка ветвей и нестрогих сравнений.

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

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

Строки с NULL в исходных данных
Норма

Получили значение из ветви ИНАЧЕ или обработки ЕСТЬ NULL

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

NULL просочился в итоговое поле

Граничные значения (например, ровно 10 при условии < 10)
Норма

Попали в ожидаемую ветвь согласно строгости сравнения

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

Граница отнесена не к той категории

Тип итогового поля
Норма

Одинаковый тип во всех строках результата

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

Смешение типов или обрезанные строки

Если запрос используется в отчёте СКД, дополнительно проверьте итоги по группировкам: категория, вычисленная через ВЫБОР, должна корректно группироваться, а не распадаться на отдельные строки из-за различий в представлении.

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

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

Технически синтаксис это допускает, но делать так не следует: условие с ВЫБОР не может использовать индексы, и СУБД будет сканировать всю таблицу. Фильтрацию выражайте прямыми сравнениями полей, а ВЫБОР оставьте для списка выбираемых полей.

Что вернёт ВЫБОР, если ни одно условие не выполнилось и ИНАЧЕ нет?

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

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

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

Можно ли в ТОГДА вернуть значение перечисления или ссылку?

Да, допустимы любые типы: примитивные, ссылки, перечисления через ЗНАЧЕНИЕ(Перечисление.Имя.Значение). Главное — чтобы все ветви возвращали совместимые типы, иначе получите ошибку выполнения или составной тип поля с сопутствующими ограничениями.

Влияет ли количество ветвей КОГДА на скорость запроса?

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

Как отладить сложный ВЫБОР с несколькими условиями?

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

Итог

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

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