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