Разработка эффективных отчетов в среде 1С:Предприятие 8 невозможна без глубокого понимания языка запросов. Одним из наиболее мощных, но иногда вызывающих трудности инструментов является оператор КОГДА. Этот оператор позволяет реализовать сложную логику выборки данных, заменяя стандартные конструкции "Если-То-Иначе" непосредственно внутри SQL-подобного запроса.

Многие начинающие разработчики путают его с оператором ГДЕ или ИМЕЮЩИЕ, что приводит к логическим ошибкам в формировании выборок. Правильное применение КОГДА позволяет трансформировать данные "на лету", присваивать новые значения полям в зависимости от условий и формировать сложные аналитические срезы без использования дополнительных временных таблиц.

В этой статье мы детально разберем синтаксис, области применения и типичные ошибки при использовании данного оператора. Вы научитесь писать оптимизированный код, который будет выполняться быстрее и понятнее для поддержки.

Синтаксическая структура и базовое применение

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

Классическая форма записи напоминает конструкцию switch-case в языках программирования типа C# или Java. Она позволяет проверить одно поле на соответствие нескольким значениям и вернуть соответствующий результат. Это особенно удобно при категоризации данных, например, при присвоении статусов заказам или группировке товаров по типам.

Рассмотрим базовый пример, где мы хотим вывести текстовое описание статуса документа вместо его внутреннего идентификатора:

ВЫБРАТЬ

Заказы.Ссылка,

Заказы.Дата,

КОГДА Заказы.Статус

ТОГДА ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказов.Новый) ТОГДА "Новый"

ТОГДА ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказов.ВРаботе) ТОГДА "В работе"

ТОГДА ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказов.Завершен) ТОГДА "Завершен"

ИНАЧЕ "Неизвестно"

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

ИЗ

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

Здесь мы видим, как КОГДА преобразует ссылку на элемент перечисления в понятную строку. Обратите внимание, что каждое условие начинается с ключевого слова ТОГДА после проверяемого значения, а завершается словом ТОГДА перед возвращаемым результатом. Завершается блок словом КОНЕЦ.

💡

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

Использование в условиях отбора (ГДЕ и ИМЕЮЩИЕ)

Помимо формирования колонок, оператор КОГДА часто применяется внутри условий отбора для реализации нелинейной логики фильтрации. Это позволяет заменить несколько операторов ИЛИ более читаемой конструкцией, особенно когда условия зависят от параметров, передаваемых в запрос.

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

Пример реализации динамической фильтрации:

ВЫБРАТЬ

РеализацияТоваровУслуг.Ссылка,

РеализацияТоваровУслуг.Дата

ИЗ

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

ГДЕ

РеализацияТоваровУслуг.Дата МЕЖДУ

КОГДА &НачалоПериода ЕСТЬ NULL ТОГДА НАЧАЛОПЕРИОДА(ТЕКУЩАЯДАТА(), МЕСЯЦ)

ИНАЧЕ &НачалоПериода

КОНЕЦ

И

РеализацияТоваровУслуг.Дата МЕЖДУ

КОГДА &КонецПериода ЕСТЬ NULL ТОГДА КОНЕЦПЕРИОДА(ТЕКУЩАЯДАТА(), МЕСЯЦ)

ИНАЧЕ &КонецПериода

КОНЕЦ

В данном случае, если параметр &НачалоПериода не заполнен (равен NULL), система автоматически подставит начало текущего месяца. Это делает код универсальным и избавляет от необходимости писать два разных запроса или использовать временные таблицы для хранения границ периода.

☑️ Проверка логики условий

Выполнено: 0 / 4

Вложенные конструкции и приоритет операций

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

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

Рассмотрим пример вложенной структуры для расчета коэффициента скидки:

ВЫБРАТЬ

Номенклатура.Ссылка,

КОГДА Номенклатура.ВидНоменклатуры

ТОГДА ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Товар) ТОГДА

(КОГДА Номенклатура.СтавкаНДС

ТОГДА ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.БезНДС) ТОГДА 1.0

ИНАЧЕ 0.8

КОНЕЦ)

ИНАЧЕ 1.0

КОНЕЦ КАК Коэффициент

ИЗ

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

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

⚠️ Внимание: Глубокая вложенность (более 3 уровней) затрудняет поддержку кода. Если ваша логика становится слишком сложной, рассмотрите возможность вычисления части значений в отдельном запросе или в коде 1С перед выводом.

📊 Как вы предпочитаете решать сложные условия?
В одном большом запросе
Через временные таблицы
В коде 1С перед выводом
С помощью СКД

Сравнение с оператором ВЫБОР и особенности типизации

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

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

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

Тип в первой ветви Тип во второй ветви Результирующий тип Статус
Число (10) Число (20.5) Число Допустимо
Строка ("А") Строка ("Б") Строка Допустимо
Число (0) Строка ("0") Неопределено Ошибка типов
Дата NULL Дата Допустимо

Особое внимание следует уделить значению NULL (или ЕСТЬ NULL). Пустое значение может быть возвращено из любой ветви, но при сравнении внутри условия КОГДА необходимо использовать специальный синтаксис ЕСТЬ NULL, так как обычное сравнение = NULL всегда вернет ложь.

💡

Все ветви оператора КОГДА должны возвращать данные одного типа или типов, которые система может автоматически привести к общему типу без потери смысла.

Оптимизация производительности при использовании КОГДА

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

Если оператор КОГДА используется для подстановки параметров, которые затем участвуют в сравнении с индексируемыми полями (например, дата или ссылка), система обычно справляется хорошо. Однако, если вы используете его для вычисления значений полей таблицы и последующей фильтрации по этим вычисленным значениям, это гарантированно приведет к полному сканированию таблицы.

Рекомендуется придерживаться следующих правил для сохранения высокой скорости работы:

  • 🚀 Старайтесь выносить логику КОГДА в список выбираемых полей, а не в условие ГДЕ, если это возможно.
  • 🚀 Избегайте использования функций внутри условий КОГДА, которые обращаются к другим таблицам или выполняют тяжелые вычисления.
  • 🚀 Проверяйте план выполнения запроса через консоль отладки, чтобы убедиться, что используются индексы.

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

⚠️ Внимание: Интерфейс и возможности конструктора запросов могут меняться в новых релизах платформы 1С. Всегда проверяйте актуальность синтаксиса в справочной системе вашей конфигурации, если код ведет себя неожиданно.

Секрет быстрой работы

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

Типичные ошибки и способы их устранения

При работе с оператором КОГДА разработчики часто сталкиваются с рядом типовых проблем. Понимание этих ошибок поможет вам писать более надежный код и быстрее находить причины сбоев в отчетах.

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

Другая частая проблема связана с обработкой NULL. Разработчики пытаются написать КОГДА Поле = NULL, что никогда не сработает. Правильный синтаксис требует использования конструкции ЕСТЬ NULL. Кроме того,

  • ❌ Ошибка: Пропущено слово ТОГДА после значения условия.
  • ❌ Ошибка: Несовместимые типы данных в разных ветвях (число и строка).
  • ❌ Ошибка: Использование = NULL вместо ЕСТЬ NULL.

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

💡

При возникновении ошибки "Неверное использование оператора КОГДА" проверьте, не забыли ли вы указать псевдоним поля после конструкции, используя ключевое слово КАК.

Практические примеры для разных задач

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

Сценарий 1: Группировка контрагентов по типу. Часто требуется разделить юридических и физических лиц для разных печатных форм. Вместо создания двух разных отчетов, можно использовать один запрос с флагом:

ВЫБРАТЬ

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

КОГДА Контрагенты.ЭтоФизическоеЛицо

ТОГДА ИСТИНА ТОГДА "Физлицо"

ИНАЧЕ "Юрлицо"

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

ИЗ

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

Сценарий 2: Расчет приоритета заказа. Если нужно выделить срочные заказы, которые просрочены или имеют высокий статус важности:

ВЫБРАТЬ

Заказы.Номер,

КОГДА Заказы.ДатаИсполнения < ТЕКУЩАЯДАТА()

ТОГДА 1

ТОГДА Заказы.Приоритет

КОНЕЦ КАК ПриоритетРасчетный

ИЗ

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

УПОРЯДОЧИТЬ ПО

ПриоритетРасчетный УБЫВ

В этом примере мы искусственно завышаем приоритет (устанавливаем в 1, что обычно означает наивысший приоритет в сортировке по убыванию, если 1 — это максимум, или корректируем логику в зависимости от системы) для просроченных заказов, чтобы они всегда были вверху списка.

Можно ли использовать оператор КОГДА без блока ИНАЧЕ?

Да, блок ИНАЧЕ не является обязательным. Если ни одно из условий не выполнено и блок ИНАЧЕ отсутствует, результатом выражения будет значение NULL (Пустая ссылка). Это нужно учитывать при дальнейшей обработке данных, чтобы избежать ошибок деления на ноль или неверных сравнений.

В чем разница между КОГДА в запросе и Если в коде 1С?

Оператор КОГДА выполняется на стороне сервера баз данных (или сервера 1С при работе с файловой базой) в процессе формирования набора записей. Конструкция Если в коде 1С выполняется на клиенте или сервере приложений уже после получения данных. Использование КОГДА эффективнее для больших объемов данных, так как уменьшает сетевой трафик и нагрузку на клиент.

Как проверить значение NULL внутри оператора КОГДА?

Для проверки на пустое значение используется специальный синтаксис: КОГДА Поле ЕСТЬ NULL ТОГДА... Обычное сравнение Поле = NULL всегда возвращает ложь, так как в стандартной логике SQL и запросов 1С неизвестное значение не равно самому себе.

Влияет ли КОГДА на использование индексов?

Если КОГДА используется в списке выбираемых полей, на индексы это не влияет. Если же он используется в условии ГДЕ для формирования значения, с которым сравнивается индексируемое поле (например, ГДЕ Дата > КОГДА..), индексы могут использоваться. Но если вы сравниваете само поле с результатом КОГДА, зависящим от других полей этой же таблицы, использование индексов может быть затруднено.