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