Функция КОГДА в языке запросов 1С:Предприятие 8 — это мощный инструмент для условной логики, который позволяет трансформировать данные прямо в SQL-подобных конструкциях. Она аналогична оператору CASE WHEN в стандартном SQL, но имеет специфический синтаксис и нюансы работы в экосистеме 1С. Без грамотного использования этой функции сложно обойтись при создании сложных отчётов, обработке разнородных данных или реализации бизнес-логики непосредственно в запросах.
В этой статье мы разберём не только базовый синтаксис КОГДА...ТОГДА...ИНАЧЕ, но и продвинутые сценарии: вложенные условия, оптимизацию производительности, типовые ошибки и альтернативные подходы. Особое внимание уделим различиям между КОГДА и ВЫБОР, а также тонкостям работы с NULL-значениями. Материал будет полезен как начинающим разработчикам, так и опытным программистам 1С, которые хотятть более эффективные и читаемые запросы.
Базовый синтаксис функции КОГДА
Конструкция КОГДА...ТОГДА...ИНАЧЕ в запросах 1С имеет следующий формат:
ВЫБРАТЬ
КОГДА Условие1 ТОГДА Значение1
КОГДА Условие2 ТОГДА Значение2
ИНАЧЕ ЗначениеПоУмолчанию
КОНЕЦ КАК ПолеРезультата
Где:
- 🔹 УсловиеN — логическое выражение (например,
СуммаДокумента > 10000илиДатаДокумента = &ТекущаяДата) - 🔹 ЗначениеN — результат, возвращаемый при истинности условия (может быть константой, полем или выражением)
- 🔹 ИНАЧЕ — обязательная секция, выполняемая если ни одно из условий не сработало
Пример простейшего использования:
ВЫБРАТЬ
КОГДА СуммаДокумента > 10000 ТОГДА"Крупная сделка"
КОГДА СуммаДокумента > 5000 ТОГДА"Средняя сделка"
ИНАЧЕ"Мелкая сделка"
КОНЕЦ КАК КатегорияСделки
ИЗ Документ.РеализацияТоваровУслуг
Всегда указывайте секцию ИНАЧЕ, даже если уверены, что все случаи обработаны. Это защитит запрос от неожиданных NULL-значений и упростит отладку.
Сравнение КОГДА и ВЫБОР: что выбрать?
В 1С существует два способа реализовать условную логику в запросах: КОГДА и ВЫБОР. Несмотря на схожий функционал, у них есть ключевые различия:
| Критерий | Функция КОГДА | Функция ВЫБОР |
|---|---|---|
| Синтаксис | Более гибкий, позволяет сложные условия | Проще для простых замен значений |
| Производительность | Может быть медленнее при множестве условий | Оптимизирована для простых замен |
| Читаемость | Лучше для сложной логики | Лучше для простых маппингов |
| Обработка NULL | Требует явной обработки | Автоматически пропускает NULL |
Пример использования ВЫБОР для простой замены:
ВЫБРАТЬ
ВЫБОР
КОГДА ВидДокумента = ЗНАЧЕНИЕ(Справочник.ВидыДокументов.ЗаказПокупателя)
ТОГДА"Заказ"
КОГДА ВидДокумента = ЗНАЧЕНИЕ(Справочник.ВидыДокументов.Реализация)
ТОГДА"Продажа"
ИНАЧЕ"Прочее"
КОНЕЦ КАК ТипОперации
Продвинутые техники: вложенные условия и оптимизация
Функция КОГДА поддерживает вложенные конструкции, что позволяет реализовывать сложную логику без разбиения на несколько запросов. Например:
ВЫБРАТЬ
КОГДА ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОпераций.Покупка)
ТОГДА КОГДА Сумма > 100000 ТОГДА"Крупная покупка"
ИНАЧЕ"Мелкая покупка"
КОНЕЦ
КОГДА ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОпераций.Продажа)
ТОГДА КОГДА Сумма > 50000 ТОГДА"Крупная продажа"
ИНАЧЕ"Мелкая продажа"
КОНЕЦ
ИНАЧЕ"Другая операция"
КОНЕЦ КАК КатегорияОперации
Однако вложенные КОГДА могут значительно снижать производительность при работе с большими наборами данных. Оптимизировать такие запросы помогают:
- 📌 Предварительная фильтрация данных в секции
ГДЕ - 📌 Использование временных таблиц для промежуточных результатов
- 📌 Замена вложенных условий на соединения с справочниками
Как ускорить запрос с множеством КОГДА?
Для запросов с более чем 5-7 условиями в КОГДА рассмотрите вариант переноса логики в виртуальную таблицу или временную таблицу с предварительно рассчитанными категориями.
Типовые ошибки и как их избежать
Даже опытные разработчики допускают ошибки при работе с КОГДА. Вот наиболее распространённые:
⚠️ Внимание: Если в условии используется сравнение с NULL (например,КОГДА Поле = NULL), оно никогда не сработает. Для проверки на NULL используйтеЕСТЬNULL(Поле, 0) = 0илиПоле ЕСТЬ NULL.
Другие распространённые проблемы:
- 🚫 Забытая секция
ИНАЧЕ— приводит к NULL в результатах - 🚫 Сравнение разных типов (например, число со строкой) — вызывает ошибки выполнения
- 🚫 Избыточные условия — когда первое условие перекрывает все остальные
- 🚫 Использование функций в условиях (например,
НАЧИНАЕТСЯСТРОКОЙ) — тормозит запрос
Пример ошибочного кода:
-- НЕПРАВИЛЬНО: сравнение с NULL
ВЫБРАТЬ
КОГДА Статус = NULL ТОГДА"Без статуса" -- Никогда не сработает!
ИНАЧЕ Статус
КОНЕЦ КАК СтатусДокумента
Правильный вариант:
-- ПРАВИЛЬНО: проверка на NULL
ВЫБРАТЬ
КОГДА Статус ЕСТЬ NULL ТОГДА"Без статуса"
ИНАЧЕ Статус
КОНЕЦ КАК СтатусДокумента
Работа с датами и временными функциями
Функция КОГДА часто используется для категоризации данных по временным периодам. Например, распределение документов по кварталам:
ВЫБРАТЬ
КОГДА МЕСЯЦ(ДатаДокумента) В (1,2,3) ТОГДА"Q1"
КОГДА МЕСЯЦ(ДатаДокумента) В (4,5,6) ТОГДА"Q2"
КОГДА МЕСЯЦ(ДатаДокумента) В (7,8,9) ТОГДА"Q3"
ИНАЧЕ"Q4"
КОНЕЦ КАК Квартал,
СУММА(СуммаДокумента) КАК ИтогоПоКварталу
ИЗ Документ.РеализацияТоваровУслуг
СГРУППИРОВАТЬ ПО КОГДА...
Для работы с текущей датой удобно использовать параметры:
ВЫБРАТЬ
КОГДА ДатаДокумента = &ТекущаяДата ТОГДА"Сегодня"
КОГДА ДатаДокумента >= НАЧАЛОДНЯ(&ТекущаяДата) И ДатаДокумента < КОНЕЦДНЯ(&ТекущаяДата) ТОГДА"Текущий день"
ИНАЧЕ"Прошлые периоды"
КОНЕЦ КАК Период
Используются ли индексируемые поля в условиях?|Учтена ли временная зона?|Проверены ли граничные случаи (например, 29 февраля)?|Оптимизированы ли функции над датами (например, ГОД(Дата) вместо Дата >=...)?-->
Оптимизация производительности
Запросы с множеством условий КОГДА могут становиться"бутылочным горлышком" производительности. Основные способы оптимизации:
- 🔧 Перенесите логику в виртуальные таблицы — если категоризация используется часто, создайте регистр сведений с предварительно рассчитанными значениями.
- 🔧 Используйте временные таблицы для промежуточных результатов:
ВЫБРАТЬ
Данные.Ссылка,
КОГДА Данные.Сумма > 10000 ТОГДА"Большая"
ИНАЧЕ"Малая"
КОНЕЦ КАК Категория
ПОМЕСТИТЬ ВТКатегории
ИЗ (
ВЫБРАТЬ
Ссылка,
Сумма
ИЗ Документ.РеализацияТоваровУслуг
) КАК Данные
- 🔧 Замените сложные условия на соединения — вместо
КОГДА ВидДокумента = XиспользуйтеЛЕВОЕ СОЕДИНЕНИЕсо справочником видов. - 🔧 Ограничивайте данные в секции ГДЕ — фильтруйте записи до применения
КОГДА.
⚠️ Внимание: При использовании КОГДА с агрегатными функциями (например, СУММА(КОГДА...)) запрос может выполняться значительно дольше. В таких случаях лучше использовать подзапросы или временные таблицы.
Практические примеры для разных задач
Рассмотрим реальные сценарии применения КОГДА в бизнес-задачах:
1. Сегментация клиентов по сумме покупок:
ВЫБРАТЬ
Клиент,
СУММА(СуммаДокумента) КАК ОбщаяСумма,
КОГДА СУММА(СуммаДокумента) > 100000 ТОГДА"VIP"
КОГДА СУММА(СуммаДокумента) > 50000 ТОГДА"Премиум"
КОГДА СУММА(СуммаДокумента) > 10000 ТОГДА"Стандарт"
ИНАЧЕ"Новый"
КОНЕЦ КАК КатегорияКлиента
ИЗ Документ.РеализацияТоваровУслуг КАК Продажи
СГРУППИРОВАТЬ ПО Клиент
2. Анализ просроченных задолжений:
ВЫБРАТЬ
Контрагент,
СуммаДолга,
КОГДА ДниПросрочки > 90 ТОГДА"Критическая"
КОГДА ДниПросрочки > 30 ТОГДА"Высокая"
КОГДА ДниПросрочки > 0 ТОГДА"Незначительная"
ИНАЧЕ"В срок"
КОНЕЦ КАК СтатусДолга
ИЗ (
ВЫБРАТЬ
Контрагент,
Сумма КАК СуммаДолга,
РАЗНОСТЬДАТ(ТЕКУЩАЯДАТА, ДатаОплаты, ДЕНЬ) КАК ДниПросрочки
ИЗ Документ.СчетаКОплате
ГДЕ Не Оплачен
) КАК Долги
3. Трансформация статусов документов:
ВЫБРАТЬ
Ссылка,
КОГДА Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыДокументов.Проведен)
ТОГДА"Активен"
КОГДА Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыДокументов.Отменен)
ТОГДА"Отменён"
КОГДА Статус ЕСТЬ NULL
ТОГДА"Черновик"
ИНАЧЕ"Другой"
КОНЕЦ КАК СтатусДляОтчета
ИЗ Документ.ЗаказПокупателя
Для сложных отчётов с множеством категорий лучше использовать механизм системы компоновки данных (СКД), где логику категоризации можно вынести в настройки отчёта.
FAQ: Частые вопросы по функции КОГДА
Можно ли использовать КОГДА без секции ИНАЧЕ?
Технически можно, но крайне не рекомендуется. Без ИНАЧЕ для записей, не попадающих ни под одно условие, будет возвращаться NULL, что может привести к ошибкам в дальнейшей обработке данных. Всегда указывайте значение по умолчанию, даже если оно просто дублирует одно из условий.
Как сравнить поле с несколькими значениями в одном условии?
Используйте оператор В (аналог IN в SQL):
КОГДА ВидДокумента В (
ЗНАЧЕНИЕ(Справочник.ВидыДокументов.ЗаказПокупателя),
ЗНАЧЕНИЕ(Справочник.ВидыДокументов.СчётНаОплату)
) ТОГДА"Продажи"
Почему запрос с КОГДА работает медленно?
Основные причины:
- Слишком много вложенных условий (более 5-7 уровней)
- Использование функций над полями в условиях (например,
ЛЕВ(Наименование, 3) ="АБВ") - Отсутствие индексов на полях, используемых в условиях
- Применение
КОГДАк большим наборам данных без предварительной фильтрации
Решения: оптимизируйте условия, используйте временные таблицы, переносите логику в виртуальные таблицы.
Можно ли в КОГДА использовать подзапросы?
Да, но с осторожностью. Подзапросы в условиях КОГДА могут значительно замедлить выполнение. Пример:
КОГДА Сумма > (ВЫБРАТЬ СРЕДНЕЕ(Сумма) ИЗ Документ.РеализацияТоваровУслуг)
ТОГДА"Выше среднего"
Лучше вынести такое значение в параметр или временную таблицу.
Как отлаживать ошибки в запросах с КОГДА?
Используйте следующие техники:
- 🐛 Разбивайте сложный запрос на части и проверяйте каждую отдельно
- 🐛 Заменяйте условия на константы (например,
КОГДА 1=1 ТОГДА...) для проверки логики - 🐛 Используйте конструктор запросов в 1С для визуального контроля
- 🐛 Проверяйте типы данных в условиях (например, сравнение числа со строкой)