Работа с перечислениями в запросах 1С часто вызывает вопросы у разработчиков, особенно когда речь заходит о конструкциях КОГДА..ТОГДА. На первый взгляд, эти операторы кажутся взаимозаменяемыми, но на практике их неправильное использование может привести к ошибкам в логике, падению производительности или даже некорректным результатам отчетов. В этой статье мы детально разберем, в каких случаях следует применять КОГДА, а когда — ТОГДА, рассмотрим нюансы работы с перечислениями разных типов и покажем, как оптимизировать запросы для ускорения их выполнения.

Особое внимание уделим типичным ошибкам, которые допускают даже опытные программисты 1С. Например, многие не учитывают, что ТОГДА может срабатывать не так, как ожидалось, при работе с составными перечислениями или когда в условии участвуют NULL-значения. Также разберемся, как правильно комбинировать эти операторы с другими конструкциями языка запросов — такими как ВЫБРАТЬ ПЕРВЫЕ или ГДЕ.

Статья будет полезна как начинающим разработчикам, которые только осваивают 1С:Предприятие 8, так и опытным специалистам, желающим систематизировать свои знания и избежать скрытых ошибок в коде. Все примеры приведены для актуальных версий платформы (8.3.20+), но основные принципы остаются неизменными и для более ранних релизов.

Чем отличаются КОГДА и ТОГДА в синтаксисе запросов 1С

Начнем с базового различия между этими двумя операторами. В языке запросов 1С:Предприятие:

  • 🔹 КОГДА — это часть конструкции ВЫБОР КОГДА..ТОГДА, которая работает аналогично оператору CASE WHEN..THEN в SQL. Она позволяет реализовать условную логику прямо в теле запроса, не прибегая к постобработке результатов.
  • 🔹 ТОГДА — это обязательная пара к КОГДА, указывающая, какое значение должно возвращаться, если условие после КОГДА истинно. Без ТОГДА конструкция КОГДА не имеет смысла и вызовет синтаксическую ошибку.

Важно понимать, что КОГДА..ТОГДА — это не два отдельных оператора, а единая конструкция с жесткой структурой. Например, следующий запрос вернет ошибку:

ВЫБРАТЬ

Номенклатура.Наименование КАК Товар,

КОГДА Номенклатура.ВидНоменклатуры = Перечисление.ВидыНоменклатуры.Товар

ТОГДА "Товар"

ИНАЧЕ "Услуга"

ИЗ

Справочник.Номенклатура КАК Номенклатура

Ошибка здесь в том, что после КОГДА отсутствует ТОГДА для второго варианта (хотя логически он подразумевается через ИНАЧЕ). Правильный вариант:

ВЫБРАТЬ

Номенклатура.Наименование КАК Товар,

ВЫБОР

КОГДА Номенклатура.ВидНоменклатуры = Перечисление.ВидыНоменклатуры.Товар

ТОГДА "Товар"

ИНАЧЕ "Услуга"

КОНЕЦ КАК ТипНоменклатуры

ИЗ

Справочник.Номенклатура КАК Номенклатура

💡

Всегда проверяйте парность операторов КОГДА и ТОГДА. Если в запросе используется ВЫБОР, то после последнего КОГДА..ТОГДА должен идти ИНАЧЕ или КОНЕЦ.

Когда использовать КОГДА без ТОГДА: мифы и реальность

В сети можно встретить утверждения, что КОГДА якобы может использоваться самостоятельно — например, в фильтрах (ГДЕ) или при формировании временных таблиц. Это опасное заблуждение! В языке запросов 1С КОГДА всегда требует парного ТОГДА (или ИНАЧЕ), за исключением одного случая — когда он применяется в составе конструкции ВЫРАЗИТЬ для создания вычисляемых полей.

Рассмотрим корректный пример с ВЫРАЗИТЬ:

ВЫБРАТЬ

ВЫРАЗИТЬ(ВЫБОР

КОГДА Документ.СуммаДокумента > 100000

ТОГДА "Крупная сделка"

ИНАЧЕ "Стандартная сделка"

КОНЕЦ КАК ТипСделки)

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

Здесь КОГДА используется именно как часть ВЫБОР..КОНЕЦ, а не как самостоятельный оператор. Попытка написать так:

ВЫБРАТЬ

КОГДА Документ.СуммаДокумента > 100000 КАК КрупнаяСделка

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

приведет к ошибке компиляции запроса. Это правило действует во всех версиях платформы 1С 8.x.

📊 Как часто вы используете конструкцию ВЫБОР КОГДА..ТОГДА в запросах 1С?
Постоянно
Иногда
Редко
Никогда

Работа с перечислениями: КОГДА для проверки значений

Основное применение конструкции КОГДА..ТОГДА — это работа с полями типа Перечисление. В отличие от числовых или строковых полей, перечисления в 1С имеют фиксированный набор значений, что делает их идеальными кандидатами для условной логики в запросах.

Рассмотрим практический пример. Допустим, у нас есть справочник Контрагенты с реквизитом ВидКонтрагента (тип — перечисление ВидыКонтрагентов с значениями Поставщик, Покупатель, Комиссионер). Нам нужно выбрать контрагентов и присвоить им текстовые метки в зависимости от вида:

ВЫБРАТЬ

Контрагент.Наименование КАК Название,

ВЫБОР

КОГДА Контрагент.ВидКонтрагента = Перечисление.ВидыКонтрагентов.Поставщик

ТОГДА "Поставщик"

КОГДА Контрагент.ВидКонтрагента = Перечисление.ВидыКонтрагентов.Покупатель

ТОГДА "Покупатель"

КОГДА Контрагент.ВидКонтрагента = Перечисление.ВидыКонтрагентов.Комиссионер

ТОГДА "Комиссионер"

ИНАЧЕ "Неопределен"

КОНЕЦ КАК ТипКонтрагента

ИЗ

Справочник.Контрагенты КАК Контрагент

Обратите внимание на несколько ключевых моментов:

  • 🔸 Для сравнения используется оператор =, а не В (хотя последний тоже допустим для перечислений).
  • 🔸 Каждое значение перечисления указывается с полным путем: Перечисление.ИмяПеречисления.Значение.
  • 🔸 Последний вариант обработан через ИНАЧЕ — это хорошая практика, чтобы избежать NULL в результате.
Что будет, если не указать ИНАЧЕ?

Если в конструкции ВЫБОР..КОНЕЦ отсутствует блок ИНАЧЕ, то для всех значений, не попадающих ни под одно условие КОГДА, будет возвращаться NULL. Это может привести к ошибкам в отчетах или некорректной фильтрации данных.

Для составных перечислений (когда одно поле может содержать несколько значений одновременно) логика усложняется. В этом случае лучше использовать функцию ВЫБРАТЬРАЗЛИЧНЫЕ или проверять вхождение через В:

ВЫБРАТЬ

Документ.Номер КАК НомерДокумента,

ВЫБОР

КОГДА Перечисление.ВидыОпераций.Поступление В Документ.ВидыОпераций

ТОГДА "Поступление"

КОГДА Перечисление.ВидыОпераций.Реализация В Документ.ВидыОпераций

ТОГДА "Реализация"

КОНЕЦ КАК ТипОперации

ИЗ

Документ.Операции КАК Документ

ТОГДА как часть условной логики: когда его можно опустить

Единственный случай, когда ТОГДА можно "опустить" — это использование сокращенной формы записи с ИНАЧЕ. Однако это не означает, что оператор пропадает: он просто подразумевается. Например, следующий запрос корректен:

ВЫБРАТЬ

ВЫБОР

КОГДА Документ.Оплачено = ИСТИНА ТОГДА "Оплачен"

ИНАЧЕ "Не оплачен"

КОНЕЦ КАК СтатусОплаты

ИЗ

Документ.ЗаказыПокупателей КАК Документ

Но если попытаться написать так:

ВЫБРАТЬ

ВЫБОР

КОГДА Документ.Оплачено = ИСТИНА "Оплачен"

ИНАЧЕ "Не оплачен"

КОНЕЦ КАК СтатусОплаты

ИЗ

Документ.ЗаказыПокупателей КАК Документ

то платформа выдаст ошибку, так как после КОГДА обязательно должно идти ТОГДА, даже если условие одно.

Сумма * 0.1

  • 📌 Вызовы функций: ТОГДА ЛЕВ(Документ.Номер, 3)
  • 📌 Вложенные конструкции ВЫБОР: ТОГДА ВЫБОР КОГДА.. КОНЕЦ
  • После каждого КОГДА должно идти ТОГДА|ТОГДА может содержать выражения и функции|Для перечислений используйте полный путь к значению|Всегда закрывайте конструкцию КОНЕЦ-->

    Производительность: что быстрее — КОГДА или фильтрация через ГДЕ

    Один из самых распространенных вопросов: что эффективнее с точки зрения производительности — использовать КОГДА..ТОГДА в выборке или предварительно отфильтровать данные через ГДЕ? Ответ зависит от конкретной задачи, но есть общие рекомендации.

    Если вам нужно просто отобрать записи по условию (например, только документы с определенным статусом), то ГДЕ будет оптимальнее:

    ВЫБРАТЬ
    

    Документ.Номер

    ИЗ

    Документ.ЗаказыПокупателей КАК Документ

    ГДЕ

    Документ.Статус = Перечисление.СтатусыЗаказов.Оплачен

    Если же требуется вернуть разные значения в зависимости от условия (например, текстовые метки для разных статусов), то ВЫБОР КОГДА..ТОГДА — единственный вариант:

    ВЫБРАТЬ
    

    Документ.Номер,

    ВЫБОР

    КОГДА Документ.Статус = Перечисление.СтатусыЗаказов.Оплачен

    ТОГДА "Оплачен"

    КОГДА Документ.Статус = Перечисление.СтатусыЗаказов.Отгружен

    ТОГДА "Отгружен"

    КОНЕЦ КАК СтатусТекст

    ИЗ

    Документ.ЗаказыПокупателей КАК Документ

    С точки зрения производительности:

    Подход Преимущества Недостатки Когда использовать
    ГДЕ Быстрее, так как фильтрация происходит на уровне СУБД Не позволяет трансформировать данные Для простой выборки по условию
    ВЫБОР КОГДА Гибкость в формировании выходных данных Может быть медленнее при большом объеме данных Для условной логики в результатах
    Комбинация ГДЕ + ВЫБОР Оптимальный баланс скорости и гибкости Более сложный запрос Для сложных отчетов с фильтрацией и трансформацией
    💡

    Для максимальной производительности сначала фильтруйте данные через ГДЕ, а затем применяйте ВЫБОР КОГДА..ТОГДА для трансформации результатов.

    Если запрос выполняется медленно, проверьте:

    1. 🔍 Наличие индексов на полях, используемых в условиях КОГДА.
    2. 🔍 Количество проверяемых условий — чем их больше, тем дольше выполнение.
    3. 🔍 Возможность замены ВЫБОР на соединение с справочником (например, через СОЕДИНИТЬ).

    Типичные ошибки при работе с КОГДА и ТОГДА

    Даже опытные разработчики иногда допускают ошибки при использовании этих операторов. Рассмотрим наиболее распространенные из них и способы их избежать.

    Ошибка 1: Сравнение перечислений через строковые литералы

    Некорректно:

    КОГДА Документ.Статус = "Оплачен" ТОГДА..

    Корректно:

    КОГДА Документ.Статус = Перечисление.СтатусыДокументов.Оплачен ТОГДА..

    Ошибка 2: Пропуск КОНЕЦ в конструкции ВЫБОР

    Это приведет к синтаксической ошибке. Всегда закрывайте конструкцию:

    ВЫБОР
    

    КОГДА Условие1 ТОГДА Значение1

    КОГДА Условие2 ТОГДА Значение2

    КОНЕЦ

    Ошибка 3: Использование NULL в ТОГДА без обработки

    Если в результате ТОГДА может вернуться NULL, это следует явно указать:

    КОГДА Документ.Сумма = 0 ТОГДА NULL

    Ошибка 4: Избыточные проверки для перечислений

    Если поле — перечисление, не нужно проверять все его возможные значения. Достаточно проверить нужные и использовать ИНАЧЕ:

    ВЫБОР
    

    КОГДА Документ.Тип = Перечисление.ТипыДокументов.Заказ ТОГДА "Заказ"

    КОГДА Документ.Тип = Перечисление.ТипыДокументов.Реализация ТОГДА "Реализация"

    ИНАЧЕ "Другой тип" -- Охватит все остальные значения перечисления

    КОНЕЦ

    💡

    Для отладки сложных конструкций с КОГДА..ТОГДА используйте временные таблицы. Сначала выберите данные без условий, затем добавьте логику пошагово.

    Практические примеры: от простых запросов до сложных конструкций

    Разберем несколько реальных примеров, демонстрирующих гибкость применения КОГДА..ТОГДА в разных сценариях.

    Пример 1: Категоризация документов по сумме

    ВЫБРАТЬ
    

    Документ.Номер КАК Номер,

    Документ.Дата КАК Дата,

    Документ.СуммаДокумента КАК Сумма,

    ВЫБОР

    КОГДА Документ.СуммаДокумента > 1000000 ТОГДА "Крупная сделка"

    КОГДА Документ.СуммаДокумента > 100000 ТОГДА "Средняя сделка"

    ИНАЧЕ "Мелкая сделка"

    КОНЕЦ КАК КатегорияСделки

    ИЗ

    Документ.РеализацияТоваровУслуг КАК Документ

    ГДЕ

    Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода

    Пример 2: Формирование статуса заказа на основе нескольких полей

    ВЫБРАТЬ
    

    Заказ.Номер КАК НомерЗаказа,

    ВЫБОР

    КОГДА Заказ.Оплачено И Заказ.Отгружено ТОГДА "Завершен"

    КОГДА Заказ.Оплачено И НЕ Заказ.Отгружено ТОГДА "Оплачен, не отгружен"

    КОГДА НЕ Заказ.Оплачено И Заказ.Отгружено ТОГДА "Отгружен, не оплачен"

    ИНАЧЕ "В обработке"

    КОНЕЦ КАК СтатусЗаказа

    ИЗ

    Документ.ЗаказыПокупателей КАК Заказ

    Пример 3: Использование с агрегатными функциями

    ВЫБРАТЬ
    

    Номенклатура.Наименование КАК Товар,

    СУММА(ВЫБОР

    КОГДА Документ.ВидДвижения = Перечисление.ВидыДвижений.Приход

    ТОГДА Документ.Количество

    КОГДА Документ.ВидДвижения = Перечисление.ВидыДвижений.Расход

    ТОГДА -Документ.Количество

    ИНАЧЕ 0

    КОНЕЦ) КАК Остаток

    ИЗ

    Документ.ДвиженияТоваров КАК Документ

    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

    ПО Документ.Номенклатура = Номенклатура.Ссылка

    ГРУППИРОВКА ПО

    Номенклатура.Наименование

    Обратите внимание, как в последнем примере ВЫБОР КОГДА..ТОГДА используется внутри агрегатной функции СУММА. Это мощный прием, позволяющий гибко управлять логикой расчетов прямо в запросе.

    Оптимизация запросов с КОГДА и ТОГДА

    При работе с большими объемами данных запросы с ВЫБОР КОГДА..ТОГДА могут становиться "бутылочным горлышком" производительности. Вот несколько способов их оптимизации:

    1. Перенесите статичные условия в ГДЕ

    Если какое-то условие в КОГДА отсекает большую часть данных, вынесите его в ГДЕ:

    -- Медленно:
    

    ВЫБРАТЬ

    ВЫБОР

    КОГДА Документ.Дата < &НачалоПериода ТОГДА NULL

    ИНАЧЕ Документ.Сумма

    КОНЕЦ КАК Сумма

    ИЗ Документ.Реализация КАК Документ

    -- Быстрее:

    ВЫБРАТЬ

    Документ.Сумма КАК Сумма

    ИЗ Документ.Реализация КАК Документ

    ГДЕ Документ.Дата >= &НачалоПериода

    2. Используйте временные таблицы для сложной логики

    Если в запросе много вложенных ВЫБОР-ов, разбейте его на части:

    // Шаг 1: Создаем временную таблицу с предварительными данными
    

    ВЫБРАТЬ

    Документ.Ссылка КАК Ссылка,

    Документ.Сумма,

    Документ.Статус

    ПОМЕСТИТЬ ВТДокументы

    ИЗ Документ.ЗаказыПокупателей КАК Документ

    ГДЕ Документ.Дата МЕЖДУ &Начало И &Конец;

    // Шаг 2: Работаем с временной таблицей

    ВЫБРАТЬ

    ВТДокументы.Ссылка КАК Документ,

    ВЫБОР

    КОГДА ВТДокументы.Статус = Перечисление.Статусы.Оплачен

    ТОГДА ВТДокументы.Сумма * 0.9 -- Скидка 10% для оплаченных

    ИНАЧЕ ВТДокументы.Сумма

    КОНЕЦ КАК ИтоговаяСумма

    ИЗ ВТДокументы КАК ВТДокументы

    3. Замените перечисления на соединения со справочниками

    Если перечисление часто используется в условиях, рассмотрите возможность создания справочника и соединения с ним. Это ускорит фильтрацию за счет индексов.

    4. Избегайте вложенных ВЫБОР-ов

    Глубоко вложенные конструкции ВЫБОР сложно поддерживать и они плохо оптимизируются. Лучше разбить логику на несколько полей:

    ВЫБРАТЬ
    

    Документ.Номер,

    ВЫБОР КОГДА Условие1 ТОГДА Значение1 ИНАЧЕ NULL КОНЕЦ КАК Поле1,

    ВЫБОР КОГДА Условие2 ТОГДА Значение2 ИНАЧЕ NULL КОНЕЦ КАК Поле2

    ИЗ Документ КАК Документ

    💡

    Оптимизация запросов с КОГДА..ТОГДА начинается с анализа плана выполнения. Используйте Консоль запросов в 1С для диагностики узких мест.

    FAQ: Частые вопросы по КОГДА и ТОГДА в запросах 1С

    Можно ли использовать КОГДА без ТОГДА в новых версиях 1С?

    Нет, синтаксис языка запросов 1С требует обязательного наличия ТОГДА после каждого КОГДА, независимо от версии платформы. Это правило действует и для 1С:Предприятие 8.3.20+, и для более ранних релизов. Единственное исключение — использование КОГДА в составе функции ВЫРАЗИТЬ, но и там требуется пара ТОГДА или ИНАЧЕ.

    Как правильно сравнивать значения составных перечислений?

    Для составных перечислений (когда поле может содержать несколько значений одновременно) используйте оператор В вместо =. Пример:

    КОГДА Перечисление.ВидыОпераций.Поступление В Документ.ВидыОпераций
    

    ТОГДА "Есть поступление"

    Это проверяет, входит ли указанное значение в составное перечисление. Для проверки точного совпадения (когда поле содержит только одно значение) можно использовать =.

    Почему запрос с КОГДА..ТОГДА выполняется медленно?

    Основные причины:

    1. Отсутствие индексов на полях, используемых в условиях КОГДА.
    2. Слишком много условий КОГДА (оптимально — не более 5-7).
    3. Сложные выражения в ТОГДА (например, вложенные ВЫБОР-ы).
    4. Отсутствие фильтрации через ГДЕ до применения ВЫБОР.

    Для диагностики используйте ОБЪЯСНИТЬ в Консоли запросов 1С.

    Можно ли в ТОГДА использовать подзапросы?

    Да, в блоке ТОГДА можно использовать подзапросы, но это может значительно замедлить выполнение. Пример:

    КОГДА Документ.Сумма > 100000
    

    ТОГДА (ВЫБРАТЬ МАКСИМУМ(Справочник.Контрагенты.КредитныйЛимит)

    ИЗ Справочник.Контрагенты КАК Контрагенты

    ГДЕ Контрагенты.Ссылка = Документ.Контрагент)

    Лучше заменить такое решение соединением или временной таблицей.

    Как обработать NULL в условиях КОГДА?

    Для проверки на NULL используйте специальный синтаксис:

    КОГДА Документ.Поле ЕСТЬ NULL ТОГДА "Значение не заполнено"

    Или для проверки на не-NULL:

    КОГДА Документ.Поле <> NULL ТОГДА "Значение заполнено"

    В блоке ТОГДА можно явно вернуть NULL, если это требуется по логике:

    КОГДА Условие ТОГДА NULL