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