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