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