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