В языке запросов 1С:Предприятие 8.3 конструкция КОГДА (аналог CASE в SQL) — один из самых мощных, но часто недооценённых инструментов. Она позволяет гибко трансформировать данные прямо в запросе, избегая постобработки на стороне 1С. Однако неумение правильно её применять ведёт к двум крайностям: либо к избыточной нагрузке на сервер, либо к нечитаемому коду, который сложно поддерживать.
Эта статья не просто объяснит синтаксис КОГДА..ТОГДА и его альтернативы вроде ВЫБОР. Мы разберём когда именно стоит использовать ту или иную конструкцию в зависимости от объёма данных, типа условий и требований к производительности, а также покажем типичные ошибки, которые тормозят запросы в 10–100 раз. Особое внимание уделим нюансам работы с управляемыми формами, тонким клиентом и веб-клиентом, где оптимизация запросов критична.
Если вы регулярно сталкиваетесь с задачами вроде «рассчитать скидку по сложным правилам прямо в запросе» или «преобразовать коды номенклатуры в читаемые названия без объединения с справочником», этот материал поможет выбрать правильный инструмент и избежать подводных камней.
1. Синтаксис конструкции КОГДА в 1С 8.3: базовые правила
Конструкция КОГДА в языке запросов 1С имеет два основных формата:
- 🔹 Простое условие (аналог
CASE WHENв SQL):
ВЫБРАТЬКОГДА СуммаДокумента > 100000 ТОГДА "Крупный"
КОГДА СуммаДокумента > 50000 ТОГДА "Средний"
ИНАЧЕ "Мелкий"
КАК КатегорияСделки
Здесь условия проверяются последовательно, и выполняется первое совпадение.
- 🔹 Сопоставление с выражением (аналог
CASE expression WHEN):
ВЫБРАТЬВЫБОР
КОГДА ВидДокумента = &ВидДокумента1 ТОГДА "Поступление"
КОГДА ВидДокумента = &ВидДокумента2 ТОГДА "Реализация"
КОНЕЦ КАК ТипОперации
В этом варианте сначала вычисляется выражение (
ВидДокумента), а затем его значение сравнивается с перечисленными вариантами.
Ключевые особенности синтаксиса:
- 📌 ИНАЧЕ — обязательный блок, если нужно обработать все возможные случаи. Без него результат для несовпавших условий будет
NULL. - 📌 ВЫБОР..КОНЕЦ — альтернативный синтаксис (аналог
SWITCHв некоторых языках), который удобен для сопоставления одного поля с несколькими значениями. - 📌 Вложенные КОГДА допускаются, но чрезмерная вложенность ухудшает читаемость и может тормозить выполнение.
Важно понимать, что КОГДА работает на уровне сервера 1С, поэтому его использование может как ускорить обработку (за счёт сокращения объёма передаваемых данных), так и замедлить (если условия слишком сложные). Например, запрос с десятком вложенных КОГДА для таблицы в 1 млн строк будет выполняться дольше, чем простая выборка с последующей обработкой на клиенте.
2. КОГДА vs ВЫБОР: когда что использовать
В 1С 8.3 есть две похожие конструкции для условной логики: КОГДА и ВЫБОР. Их часто путают, но у них разные сценарии применения:
| Критерий | КОГДА (CASE WHEN) | ВЫБОР (SWITCH-like) |
|---|---|---|
| Тип сравнения | Произвольные условия (Сумма > 1000, Дата МЕЖДУ..) |
Сопоставление одного выражения с фиксированными значениями (Код = 1) |
| Читаемость | Хуже при множестве условий | Лучше для переключения по кодам/идентификаторам |
| Производительность | Может тормозить при сложных условиях | Быстрее, если сравниваются простые значения |
| Типичный сценарий | Расчёт скидок, группировка по диапазонам | Преобразование кодов в названия, маршрутизация по типам документов |
Пример, где ВЫБОР предпочтительнее:
ВЫБРАТЬ
Номенклатура.Наименование,
ВЫБОР
КОГДА Номенклатура.ВидНоменклатуры = &Вид1 ТОГДА "Товар"
КОГДА Номенклатура.ВидНоменклатуры = &Вид2 ТОГДА "Услуга"
КОГДА Номенклатура.ВидНоменклатуры = &Вид3 ТОГДА "Комплект"
КОНЕЦ КАК ТипНоменклатуры
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
А здесь лучше подходит КОГДА:
ВЫБРАТЬ
КОГДА СуммаОплаты >= 100000 ТОГДА "VIP"
КОГДА СуммаОплаты >= 50000 И Клиент.Категория = &Категория1 ТОГДА "Premium"
ИНАЧЕ "Standard"
КАК УровеньКлиента
Если вам нужно сравнить одно поле с несколькими фиксированными значениями (например, коды типов документов), используйте ВЫБОР. Для сложных условий с диапазонами, вложенными проверками или вычислениями — КОГДА.
3. Типичные ошибки при использовании КОГДА и как их избежать
Даже опытные разработчики 1С допускают ошибки, которые ведут к некорректным результатам или падению производительности. Вот самые распространённые:
- 🚨 Отсутствие блока ИНАЧЕ:
Если не указать
ИНАЧЕ, то для строк, не попадающих ни под одно условие, вернётсяNULL. Это может привести к ошибкам в отчётах или логике программы. Например:// Плохо: без ИНАЧЕКОГДА СтатусЗаказа = "Оплачен" ТОГДА 1
КОГДА СтатусЗаказа = "Отгружен" ТОГДА 2
// Для статуса "Отменён" вернётся NULL!
- 🚨 Избыточные условия:
Если в цепочке
КОГДАпервое условие покрывает все остальные, последующие проверки никогда не сработают. Например:// Бессмысленная проверкаКОГДА Сумма > 0 ТОГДА "Положительная"
КОГДА Сумма > 1000 ТОГДА "Крупная" // Никогда не выполнится!
- 🚨 Сложные вычисления в каждом КОГДА:
Если вы повторяете одну и ту же тяжелую операцию (например, вызов функции или подзапроса) в каждом условии, запрос будет выполняться дольше. Лучше вынести её в отдельное поле:
ВЫБРАТЬРАЗНОСТЬДАТ(ТекущаяДата(), ДатаДокумента) КАК ДнейНазади,
КОГДА ДнейНазади > 30 ТОГДА "Просрочен"
КОГДА ДнейНазади > 7 ТОГДА "Скоро просрочка"
ИНАЧЕ "Актуален"
КАК Статус
Перед написанием цепочки КОГДА проанализируйте условия на предмет взаимного исключения. Если одно условие делает остальные бесполезными, упростите логику или разбейте запрос на части.
Ещё одна распространённая проблема — неучёт порядка условий. В 1С условия проверяются сверху вниз, и первое совпадение прерывает дальнейшие проверки. Например:
КОГДА Клиент.Категория = "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% данных в тестовую базу и сравните время выполнения.
- 🔍 Журнал регистрации:
Включите регистрацию медленных запросов в 1С (
Администрирование → Журналы регистрации). Пороговое время настройте в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 вместо ИНАЧЕ?
Это происходит, если:
- Вы забыли блок
ИНАЧЕ. - Одно из условий содержит ошибку (например, деление на ноль), и сервер прерывает выполнение.
- В условии используется поле с
NULL, и сравнение не срабатывает (например,КОГДА Поле = 1не вернёт истину, еслиПолеравноNULL). Для проверки наNULLиспользуйтеЕСТЬNULL:
КОГДА ЕСТЬNULL(Поле, 0) = 1 ТОГДА "Да"
🔹 Как оптимизировать запрос с 20-ю условиями КОГДА?
Столь большое количество условий почти всегда говорит о плохом дизайне. Рассмотрите альтернативы:
- 🔹 Замените на соединение со справочником, где условия хранятся как записи.
- 🔹 Разбейте запрос на несколько этапов (например, сначала получите данные, затем обработайте их в временной таблице).
- 🔹 Используйте регистр сведений для хранения предварительно рассчитанных категорий.
Если без КОГДА не обойтись, группируйте условия по приоритету и выносите общие части в подзапросы.
🔹 Можно ли использовать КОГДА в запросах к внешним источникам (HTTP-сервисы, REST)?
Нет, конструкция КОГДА работает только в языке запросов 1С. Для обработки данных из внешних источников используйте:
- 🔹 Функции 1С на стороне клиента/сервера.
- 🔹 Предварительную обработку данных в промежуточной таблице.
- 🔹 Скрипты на языке источника (например, SQL-процедуры, если это база данных).
🔹 Влияет ли использование КОГДА на лицензирование 1С?
Нет, конструкция КОГДА не затрагивает лицензионные ограничения. Однако сложные запросы могут увеличивать нагрузку на сервер, что косвенно влияет на:
- 🔹 Потребление ресурсов сервера 1С (важно для облачных решений с ограничением по CPU).
- 🔹 Производительность в режиме файловой базы, где все вычисления выполняются на клиенте.
⚠️ Внимание: В некоторых тарифах облачных сервисов (например, 1С:Fresh) ограничено время выполнения запросов. Слишком сложные конструкции КОГДА могут приводить к тайм-аутам.