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