К статье
Практический материал

Разработка и Конфигурация · 9 мин

Оператор КОГДА в языке запросов 1С: как строить условия в запросах

Разбираем оператор КОГДА в языке запросов 1С: синтаксис ВЫБОР КОГДА ТОГДА ИНАЧЕ КОНЕЦ, примеры, типичные ошибки и ограничения при работе с условиями.

Оператор КОГДА в языке запросов 1С — это часть конструкции условного выбора, аналог CASE в классическом SQL. Она позволяет вернуть разные значения поля в зависимости от выполнения условий прямо в тексте запроса, без постобработки результата в коде. Это один из самых востребованных приёмов при построении отчётов, динамических списков и выборок для обмена данными.

Конструкция полностью называется «ВЫБОР … КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ» (в английском синтаксисе — CASE WHEN THEN ELSE END). Слово КОГДА открывает очередную ветку условия, и веток может быть сколько угодно. Запрос проверяет условия сверху вниз и возвращает значение из первой сработавшей ветки.

Практическая ценность оператора в том, что логика классификации данных переносится на сервер СУБД: меньше кода на встроенном языке, быстрее выполнение, проще поддержка. Ниже разберём синтаксис, типовые сценарии, ограничения и ошибки, которые чаще всего встречаются у начинающих разработчиков.

Синтаксис конструкции ВЫБОР … КОГДА … ТОГДА

Полная форма оператора выглядит так:

ВЫБОР

КОГДА Продажи.Сумма > 100000

ТОГДА "Крупная"

КОГДА Продажи.Сумма > 10000

ТОГДА "Средняя"

ИНАЧЕ "Мелкая"

КОНЕЦ КАК КатегорияСделки

Обязательные элементы — ВЫБОР, хотя бы одна пара КОГДА/ТОГДА и завершающее слово КОНЕЦ. Ветка ИНАЧЕ опциональна: если её опустить и ни одно условие не выполнится, поле получит значение NULL. Это частая причина «пустых» значений в отчётах, когда разработчик забыл про непокрытые случаи.

После КОНЕЦ принято сразу указывать псевдоним поля через КАК — без псевдонима обратиться к результату в коде или в настройках СКД будет затруднительно.

Какие условия допустимы после КОГДА

После КОГДА можно использовать любое логическое выражение, допустимое в секции ГДЕ: сравнения полей с константами и параметрами, проверки В ИЕРАРХИИ, В, МЕЖДУ, ПОДОБНО, ЕСТЬ NULL, а также логические связки И, ИЛИ, НЕ со скобками. Это делает оператор гибким инструментом классификации.

ВЫБОР

КОГДА Номенклатура.ВидНоменклатуры В (&ВидыУслуг)

ТОГДА "Услуга"

КОГДА Номенклатура.СрокГодности ЕСТЬ NULL

ТОГДА "Без срока годности"

КОГДА Номенклатура.СрокГодности МЕЖДУ &Начало И &Конец

ТОГДА "Истекает скоро"

ИНАЧЕ "Обычный товар"

КОНЕЦ КАК Категория

Важно помнить про порядок проверки: условия вычисляются последовательно, и первое выполнившееся «перехватывает» строку. Поэтому более частные условия ставят выше, а более общие — ниже. Если перепутать порядок, часть строк попадёт не в ту ветку, и запрос формально останется корректным — ошибку заметят только по неверным цифрам в отчёте.

Где применять оператор КОГДА на практике

Наиболее частые сценарии использования условного выбора в запросах:

  • классификация строк отчёта по диапазонам сумм, дат, количества;
  • замена кодов и перечислений на читаемые строковые представления;
  • вычисление «знака» суммы: приход минус расход в одном поле;
  • подмена NULL безопасным значением (альтернатива ЕСТЬNULL с логикой);
  • условное соединение: выбор источника цены в зависимости от типа цен;
  • построение полей-признаков для группировок и итогов в СКД.

Характерный пример — сворачивание прихода и расхода в одну колонку с нужным знаком:

ВЫБРАТЬ

Остатки.Номенклатура,

СУММА(ВЫБОР

КОГДА Остатки.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)

ТОГДА Остатки.Количество

ИНАЧЕ -Остатки.Количество

КОНЕЦ) КАК Остаток

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК Остатки

СГРУППИРОВАТЬ ПО

Остатки.Номенклатура

Такой приём позволяет получить агрегат за один проход по таблице, без разворачивания результата в коде. В регистрах накопления с готовыми итогами он не нужен, но при выборке из таблицы движений или чужих источников данных — стандартное решение.

Если ВЫБОР используется внутри агрегатной функции (СУММА, МАКСИМУМ), проверяйте, что во всех ветках возвращается числовой тип. Смешение числа и NULL в группировке даёт корректный результат, а вот смешение числа и строки приведёт к ошибке выполнения запроса.
ПЗ
Практическое замечание

Ограничения и подводные камни

Первое ограничение — типы результата. Все ветки ТОГДА и ИНАЧЕ должны возвращать совместимые типы. Если одна ветка возвращает строку, а другая — число, запрос либо не выполнится, либо приведёт типы непредсказуемым образом. Для ссылочных типов допустим составной результат, но с ним аккуратнее работать в СКД и при выгрузке.

Второй момент — производительность. ВЫБОР в списке полей вычисляется построчно и обычно дёшев, но если условие КОГДА содержит вложенный подзапрос или обращение через разыменование к нескольким таблицам, стоимость запроса заметно растёт. В таких случаях лучше сначала собрать нужные поля соединениями во временную таблицу, а условный выбор применить уже к плоским данным.

Третий нюанс — NULL в условиях. Сравнение поля, содержащего NULL, с любым значением даёт «не истину», поэтому строка уйдёт в ИНАЧЕ или вовсе не попадёт ни в одну ветку. Если NULL для поля возможен, добавляйте явную ветку КОГДА Поле ЕСТЬ NULL или оборачивайте поле в ЕСТЬNULL до сравнения.

Типичные ошибки при работе с КОГДА

Типичные ошибки
01
Пропуск ИНАЧЕ: строки, не попавшие ни в одно условие, получают NULL, и итоги по группам «не сходятся» с контрольными цифрами.
02
Неверный порядок веток: общее условие стоит выше частного, и частная ветка никогда не срабатывает.
03
Смешение типов в ветках: строка в одной ветке и число в другой приводят к ошибке выполнения запроса или неверному приведению.
04
Забытый КОНЕЦ или псевдоним: запрос не проходит синтаксический контроль либо поле недоступно по имени в СКД.
05
Игнорирование NULL в сравниваемом поле: строки с NULL молча уходят в ИНАЧЕ, искажая классификацию.

Отдельно стоит сказать про сравнение строк: оператор «=» в запросах 1С для строк работает без учёта регистра на большинстве СУБД, но ПОДОБНО с шаблоном может вести себя иначе. Если классификация строится по текстовым признакам, проверяйте поведение на реальных данных, а не только на тестовом примере из двух строк.

Альтернативы оператору ВЫБОР

Не каждую задачу нужно решать через ВЫБОР. Если требуется просто заменить NULL значением по умолчанию, короче и читабельнее функция ЕСТЬNULL(Поле, Значение). Если нужна классификация по постоянному списку соответствий — надёжнее соединение с регистром сведений или таблицей значений, переданной как параметр.

Для сложной многоуровневой логики, где условия зависят от настроек пользователя, иногда проще получить «сырые» поля запросом и доклассифицировать строки в коде или в вычисляемых полях СКД. Вычисляемые поля СКД, кстати, поддерживают похожий синтаксис ВЫБОР и позволяют вынести оформительскую логику из запроса в настройки отчёта.

Сравнение вариантов

ВЫБОР в запросе

Подходит для классификации на лету и вычислений в агрегатах; ограничение — логика зашита в текст запроса.

ЕСТЬNULL

Короткая замена NULL значением по умолчанию; не умеет ничего, кроме подмены NULL.

Соединение с регистром сведений

Для изменяемых соответствий, которые настраивает пользователь; требует дополнительной таблицы и индексов.

Вычисляемые поля СКД

Для оформительской логики отчёта; не подходит, если результат нужен вне СКД.

Как проверить корректность запроса с условиями

После написания запроса с ВЫБОР полезно пройти короткий цикл проверки: выполнить запрос в консоли запросов на копии базы, убедиться, что каждая ветка реально срабатывает хотя бы на одной строке, и сверить количество строк в каждой категории с ожиданиями. Ветка, которая никогда не срабатывает на реальных данных, — признак ошибки в условии или в порядке проверок.

Контрольные точки

Как проверить результат

Срабатывание веток
Норма

Каждая ветка КОГДА покрывает хотя бы одну строку тестовых данных

Тревожный признак

Ветка пустая на всех данных — вероятно, условие недостижимо

Покрытие строк
Норма

Сумма строк по всем категориям равна общему числу строк выборки

Тревожный признак

Часть строк ушла в NULL или неучтённую категорию

Тип результата
Норма

Во всех ветках один и тот же тип значения

Тревожный признак

Смешанные типы, ошибка выполнения или неожиданное приведение

Итог

Что важно запомнить

КОГДА работает только внутри ВЫБОР … КОНЕЦ, ветки проверяются сверху вниз, типы результатов должны совпадать, а ветка ИНАЧЕ и обработка NULL защищают от «потерянных» строк в отчётах.

Частые вопросы об операторе КОГДА

Можно ли использовать КОГДА без слова ВЫБОР?

Нет. КОГДА существует только внутри конструкции ВЫБОР … КОНЕЦ. Отдельного оператора КОГДА в языке запросов 1С нет — в отличие, например, от секции ГДЕ, которая является самостоятельной частью запроса.

Сколько веток КОГДА допустимо в одном ВЫБОР?

Формального жёсткого ограничения нет, но на практике больше 5–7 веток — признак того, что соответствие лучше вынести в регистр сведений и получать соединением. Длинные ВЫБОР трудно читать и поддерживать.

Чем отличается ВЫБОР в запросе от ЕСТЬNULL?

ЕСТЬNULL решает одну задачу — подмену NULL указанным значением. ВЫБОР — универсальный условный оператор с произвольными условиями. Если нужна только защита от NULL, используйте ЕСТЬNULL: запись короче и понятнее.

Работает ли ВЫБОР в секции ГДЕ и в итогах?

В секции ГДЕ ВЫБОР использовать не нужно — там условия записываются напрямую логическими выражениями. В группировках и итогах ВЫБОР применяется внутри агрегатных функций (например, СУММА(ВЫБОР … КОНЕЦ)) и как поле группировки — это типовой приём для сводных отчётов.

Можно ли в ТОГДА вернуть результат другого запроса?

Возвращать можно выражения над полями, параметрами и константами; вложенные скалярные подзапросы в этой позиции не поддерживаются. Если значение нужно вычислить отдельным запросом, передайте его параметром или соедините с заранее подготовленной временной таблицей.

Почему строка попала в ИНАЧЕ, хотя условие визуально верное?

Чаще всего причина в NULL в сравниваемом поле: любое сравнение с NULL не даёт истины. Проверьте поле на NULL, добавьте ветку КОГДА Поле ЕСТЬ NULL или оберните поле в ЕСТЬNULL перед сравнением. Вторая частая причина — более общее условие выше по списку перехватило строку раньше.