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