В языке запросов 1С:Предприятие 8.3 конструкция КОГДА (аналог CASE в SQL) — один из самых мощных, но часто недооценённых инструментов. Она позволяет гибко трансформировать данные прямо в запросе, избегая постобработки на стороне . Однако неумение правильно её применять ведёт к двум крайностям: либо к избыточной нагрузке на сервер, либо к нечитаемому коду, который сложно поддерживать.

Эта статья не просто объяснит синтаксис КОГДА..ТОГДА и его альтернативы вроде ВЫБОР. Мы разберём когда именно стоит использовать ту или иную конструкцию в зависимости от объёма данных, типа условий и требований к производительности, а также покажем типичные ошибки, которые тормозят запросы в 10–100 раз. Особое внимание уделим нюансам работы с управляемыми формами, тонким клиентом и веб-клиентом, где оптимизация запросов критична.

Если вы регулярно сталкиваетесь с задачами вроде «рассчитать скидку по сложным правилам прямо в запросе» или «преобразовать коды номенклатуры в читаемые названия без объединения с справочником», этот материал поможет выбрать правильный инструмент и избежать подводных камней.

1. Синтаксис конструкции КОГДА в 1С 8.3: базовые правила

Конструкция КОГДА в языке запросов имеет два основных формата:

  • 🔹 Простое условие (аналог CASE WHEN в SQL):
    ВЫБРАТЬ
    

    КОГДА СуммаДокумента > 100000 ТОГДА "Крупный"

    КОГДА СуммаДокумента > 50000 ТОГДА "Средний"

    ИНАЧЕ "Мелкий"

    КАК КатегорияСделки

    Здесь условия проверяются последовательно, и выполняется первое совпадение.

  • 🔹 Сопоставление с выражением (аналог CASE expression WHEN):
    ВЫБРАТЬ
    

    ВЫБОР

    КОГДА ВидДокумента = &ВидДокумента1 ТОГДА "Поступление"

    КОГДА ВидДокумента = &ВидДокумента2 ТОГДА "Реализация"

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

    В этом варианте сначала вычисляется выражение (ВидДокумента), а затем его значение сравнивается с перечисленными вариантами.

Ключевые особенности синтаксиса:

  • 📌 ИНАЧЕ — обязательный блок, если нужно обработать все возможные случаи. Без него результат для несовпавших условий будет NULL.
  • 📌 ВЫБОР..КОНЕЦ — альтернативный синтаксис (аналог SWITCH в некоторых языках), который удобен для сопоставления одного поля с несколькими значениями.
  • 📌 Вложенные КОГДА допускаются, но чрезмерная вложенность ухудшает читаемость и может тормозить выполнение.
📊 Какой синтаксис КОГДА вы используете чаще?
Простое условие (WHEN..THEN)
Сопоставление с выражением (SWITCH-like)
Вложенные конструкции
Не использую, заменяю на ВЫБОР

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

2. КОГДА vs ВЫБОР: когда что использовать

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

Критерий КОГДА (CASE WHEN) ВЫБОР (SWITCH-like)
Тип сравнения Произвольные условия (Сумма > 1000, Дата МЕЖДУ..) Сопоставление одного выражения с фиксированными значениями (Код = 1)
Читаемость Хуже при множестве условий Лучше для переключения по кодам/идентификаторам
Производительность Может тормозить при сложных условиях Быстрее, если сравниваются простые значения
Типичный сценарий Расчёт скидок, группировка по диапазонам Преобразование кодов в названия, маршрутизация по типам документов

Пример, где ВЫБОР предпочтительнее:

ВЫБРАТЬ

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

ВЫБОР

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

КОГДА Номенклатура.ВидНоменклатуры = &Вид2 ТОГДА "Услуга"

КОГДА Номенклатура.ВидНоменклатуры = &Вид3 ТОГДА "Комплект"

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

ИЗ

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

А здесь лучше подходит КОГДА:

ВЫБРАТЬ

КОГДА СуммаОплаты >= 100000 ТОГДА "VIP"

КОГДА СуммаОплаты >= 50000 И Клиент.Категория = &Категория1 ТОГДА "Premium"

ИНАЧЕ "Standard"

КАК УровеньКлиента

💡

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

3. Типичные ошибки при использовании КОГДА и как их избежать

Даже опытные разработчики допускают ошибки, которые ведут к некорректным результатам или падению производительности. Вот самые распространённые:

  • 🚨 Отсутствие блока ИНАЧЕ:

    Если не указать ИНАЧЕ, то для строк, не попадающих ни под одно условие, вернётся NULL. Это может привести к ошибкам в отчётах или логике программы. Например:

    // Плохо: без ИНАЧЕ
    

    КОГДА СтатусЗаказа = "Оплачен" ТОГДА 1

    КОГДА СтатусЗаказа = "Отгружен" ТОГДА 2

    // Для статуса "Отменён" вернётся NULL!

  • 🚨 Избыточные условия:

    Если в цепочке КОГДА первое условие покрывает все остальные, последующие проверки никогда не сработают. Например:

    // Бессмысленная проверка
    

    КОГДА Сумма > 0 ТОГДА "Положительная"

    КОГДА Сумма > 1000 ТОГДА "Крупная" // Никогда не выполнится!

  • 🚨 Сложные вычисления в каждом КОГДА:

    Если вы повторяете одну и ту же тяжелую операцию (например, вызов функции или подзапроса) в каждом условии, запрос будет выполняться дольше. Лучше вынести её в отдельное поле:

    ВЫБРАТЬ
    

    РАЗНОСТЬДАТ(ТекущаяДата(), ДатаДокумента) КАК ДнейНазади,

    КОГДА ДнейНазади > 30 ТОГДА "Просрочен"

    КОГДА ДнейНазади > 7 ТОГДА "Скоро просрочка"

    ИНАЧЕ "Актуален"

    КАК Статус

💡

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

Ещё одна распространённая проблема — неучёт порядка условий. В условия проверяются сверху вниз, и первое совпадение прерывает дальнейшие проверки. Например:

КОГДА Клиент.Категория = "VIP" ТОГДА 10 // Сработает для всех VIP, даже если сумма < 1000

КОГДА СуммаЗаказа > 1000 ТОГДА 5

Чтобы избежать таких ошибок, располагайте условия от наиболее специфичных к общим.

4. Оптимизация запросов с КОГДА: как ускорить работу

Конструкция КОГДА может значительно замедлить запрос, если использовать её неэффективно. Вот ключевые правила оптимизации:

  • Избегайте вызовов функций в условиях:

    Функции вроде НАЧИНАЕТСЯСТР или НАЙТИ в каждом КОГДА заставляют сервер выполнять их для каждой строки. Например:

    // Медленно:
    

    КОГДА НАЧИНАЕТСЯСТР(Номенклатура.Артикул, "A") ТОГДА "Группа A"

    КОГДА НАЧИНАЕТСЯСТР(Номенклатура.Артикул, "B") ТОГДА "Группа B"

    Лучше использовать ПОДОБНО или предварительно рассчитать группы в отдельном поле.

  • Заменяйте множественные КОГДА на объединения:

    Если вам нужно присвоить метки на основе данных из другого справочника, вместо цепочки КОГДА используйте СОЕДИНЕНИЕ:

    // Быстрее, чем 20 условий КОГДА:
    

    ВЫБРАТЬ

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

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

    ИЗ

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

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

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

  • Используйте индексируемые поля:

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

    // Медленно, если поле не проиндексировано:
    

    КОГДА Документ.Комментарий СОДЕРЖИТ "Срочно" ТОГДА 1

Как проверить, есть ли индекс на поле?

Откройте конфигуратор, найдите таблицу в метаданных (например, Документ.РеализацияТоваровУслуг), перейдите на закладку "Индексы". Если нужного поля нет в списке, добавьте его через конструктор или вручную.

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

5. Примеры реальных задач с использованием КОГДА

Рассмотрим практические сценарии, где КОГДА помогает решить задачи эффективно.

📌 Задача 1: Расчёт скидок по сложным правилам

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

ВЫБРАТЬ

КОГДА

СуммаДокумента > 100000

И Клиент.Категория = &VIP

И Номенклатура.Вид = &Товар

ТОГДА 15 // Максимальная скидка

КОГДА

СуммаДокумента > 50000

И Клиент.Категория = &Premium

ТОГДА 10

КОГДА Номенклатура.Вид = &Услуга ТОГДА 5 // Фиксированная скидка на услуги

ИНАЧЕ 0

КАК РазмерСкидки

📌 Задача 2: Преобразование статусов в читаемый вид

В базе статусы документов хранятся в виде кодов (например, 1, 2), а в отчёте нужно показать названия ("Оплачен", "Отгружен"). Вместо объединения со справочником используем ВЫБОР:

ВЫБРАТЬ

ВЫБОР

КОГДА Статус = 1 ТОГДА "Оплачен"

КОГДА Статус = 2 ТОГДА "Отгружен"

КОГДА Статус = 3 ТОГДА "Отменён"

КОНЕЦ КАК СтатусНаименование

📌 Задача 3: Группировка по диапазонам дат

Нужно сгруппировать документы по периодам (например, "Этот месяц", "Прошлый месяц", "Ранее"). Здесь КОГДА незаменим:

ВЫБРАТЬ

КОГДА Дата МЕЖДУ НАЧАЛОМЕСЯЦА(ТекущаяДата()) И КОНЕЦМЕСЯЦА(ТекущаяДата()) ТОГДА "Этот месяц"

КОГДА Дата МЕЖДУ ДОБАВИТЬМЕСЯЦ(НАЧАЛОМЕСЯЦА(ТекущаяДата()), -1) И КОНЕЦМЕСЯЦА(ДОБАВИТЬМЕСЯЦ(ТекущаяДата(), -1)) ТОГДА "Прошлый месяц"

ИНАЧЕ "Ранее"

КАК Период

Можно ли заменить КОГДА на соединение с справочником?|Все ли условия взаимно исключают друг друга?|Есть ли блок ИНАЧЕ для обработки всех случаев?|Не повторяются ли тяжёлые вычисления в каждом КОГДА?-->

6. Альтернативы КОГДА: когда лучше обойтись без него

Иногда КОГДА — не лучший выбор. Рассмотрим альтернативы:

  • 🔄 Объединение таблиц (СОЕДИНЕНИЕ):

    Если вам нужно подставить названия вместо кодов, лучше присоединить справочник, чем перечислять все варианты в КОГДА:

    ВЫБРАТЬ
    

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

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

    ИЗ

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

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

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

  • 🔄 Виртуальные таблицы:

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

    ВЫБРАТЬ
    

    ОстаткиНоменклатурыОбороты.Номенклатура,

    ОстаткиНоменклатурыОбороты.КоличествоОборот

    ИЗ

    РегистрНакопления.ОстаткиНоменклатуры.Обороты(&НачалоПериода, &КонецПериода,) КАК ОстаткиНоменклатурыОбороты

  • 🔄 Вычисляемые поля на стороне СУБД:

    Если вы используете PostgreSQL или MS SQL, некоторые операции можно делегировать СУБД через прямые запросы или временные таблицы.

💡

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

Ещё один вариант — использование регистров сведений для хранения предварительно рассчитанных значений. Например, если вам часто нужна категория клиента по сумме покупок, можно рассчитывать её при изменении документов и хранить в регистре, а не вычислять в каждом запросе.

7. Особенности работы с КОГДА в разных клиентах 1С

Поведение запросов с КОГДА может отличаться в зависимости от типа клиента 1С:Предприятия:

  • 🖥️ Толстый клиент:

    Здесь запросы выполняются на стороне клиента, поэтому сложные конструкции КОГДА могут тормозить интерфейс. Рекомендуется переносить тяжёлую логику на сервер или использовать фоновые задания.

  • 🌐 Тонкий клиент и веб-клиент:

    Все запросы выполняются на сервере, поэтому КОГДА здесь менее опасен для производительности. Однако большое количество данных, возвращаемых клиенту, может тормозить отображение. Используйте ПЕРВЫЕ или РАЗДЕЛИТЬ НА СТРАНИЦЫ для ограничения объёма.

  • 📱 Мобильное приложение:

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

Как проверить, где выполняется запрос?

Включите отладку SQL (в конфигураторе: Сервис → Параметры → Отладка → Выводить текст запроса и план выполнения). Если в плане видно Client side, запрос выполняется на клиенте.

Для управляемых форм В таких случаях:

  • Используйте ПоместитьРезультатВКоллекцию() для асинхронной загрузки.
  • Разбивайте сложные отчёты на части (например, сначала показывайте сводные данные, а детали — по запросу пользователя).

8. Отладка и анализ производительности запросов с КОГДА

Если запрос с КОГДА работает медленно, используйте эти инструменты для диагностики:

  • 🔍 План выполнения запроса:

    В конфигураторе включите вывод плана (Сервис → Параметры → Отладка) и обратите внимание на:

    • 📊 Table Scan — означает полное сканирование таблицы (нужны индексы).
    • 📊 Nested Loops — может указывать на неэффективные соединения.

    Пример плохого плана:

    SELECT STATEMENT (cost=10000)
    

    → TABLE ACCESS FULL (Документ.РеализацияТоваровУслуг)

  • 🔍 Тестирование на тестовых данных:

    Если запрос тормозит на большой базе, проверьте его на уменьшенной копии. Например, скопируйте 10% данных в тестовую базу и сравните время выполнения.

  • 🔍 Журнал регистрации:

    Включите регистрацию медленных запросов в (Администрирование → Журналы регистрации). Пороговое время настройте в mscrconf.cfg:

    [DBMS]
    

    SlowQueryThreshold=1000 // Запросы медленнее 1 секунды

💡

Если в плане выполнения видно SORT AGGREGATE или HASH GROUP BY, это значит, что сервер тратит много ресурсов на группировку. Попробуйте упростить условия в КОГДА или разделить запрос на части.

Для анализа производительности в PostgreSQL используйте:

EXPLAIN ANALYZE [ваш запрос]

В MS SQL:

SET STATISTICS TIME ON

SET STATISTICS IO ON

[ваш запрос]

FAQ: Частые вопросы по использованию КОГДА в 1С 8.3

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

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

ВЫБРАТЬ

(ВЫБРАТЬ

КОГДА Сумма > 1000 ТОГДА "Крупный"

ИНАЧЕ "Мелкий"

КАК Размер

ИЗ Документ.ЗаказыКлиентов

ГДЕ Клиент = ВНЕШНЯЯССЫЛКА(Документ.Клиент)) КАК РазмерЗаказа

🔹 Почему КОГДА возвращает NULL вместо ИНАЧЕ?

Это происходит, если:

  1. Вы забыли блок ИНАЧЕ.
  2. Одно из условий содержит ошибку (например, деление на ноль), и сервер прерывает выполнение.
  3. В условии используется поле с NULL, и сравнение не срабатывает (например, КОГДА Поле = 1 не вернёт истину, если Поле равно NULL). Для проверки на NULL используйте ЕСТЬNULL:
КОГДА ЕСТЬNULL(Поле, 0) = 1 ТОГДА "Да"
🔹 Как оптимизировать запрос с 20-ю условиями КОГДА?

Столь большое количество условий почти всегда говорит о плохом дизайне. Рассмотрите альтернативы:

  • 🔹 Замените на соединение со справочником, где условия хранятся как записи.
  • 🔹 Разбейте запрос на несколько этапов (например, сначала получите данные, затем обработайте их в временной таблице).
  • 🔹 Используйте регистр сведений для хранения предварительно рассчитанных категорий.

Если без КОГДА не обойтись, группируйте условия по приоритету и выносите общие части в подзапросы.

🔹 Можно ли использовать КОГДА в запросах к внешним источникам (HTTP-сервисы, REST)?

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

  • 🔹 Функции на стороне клиента/сервера.
  • 🔹 Предварительную обработку данных в промежуточной таблице.
  • 🔹 Скрипты на языке источника (например, SQL-процедуры, если это база данных).
🔹 Влияет ли использование КОГДА на лицензирование 1С?

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

  • 🔹 Потребление ресурсов сервера (важно для облачных решений с ограничением по CPU).
  • 🔹 Производительность в режиме файловой базы, где все вычисления выполняются на клиенте.
⚠️ Внимание: В некоторых тарифах облачных сервисов (например, 1С:Fresh) ограничено время выполнения запросов. Слишком сложные конструкции КОГДА могут приводить к тайм-аутам.