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