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