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