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