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

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

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

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

  • 🔹 Простое условие: КОГДА Условие ТОГДА Значение1 ИНАЧЕ Значение2 — аналог тернарного оператора.
  • 🔹 Множественное ветвление: КОГДА Условие1 ТОГДА Значение1 ... КОГДА УсловиеN ТОГДА ЗначениеN ИНАЧЕ ЗначениеПоУмолчанию — аналог CASE WHEN ... THEN ... ELSE.

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

  • 📌 Ключевое слово ТОГДА обязательно после каждого условия.
  • 📌 Блок ИНАЧЕ не обязателен — если его нет, а ни одно условие не выполнилось, результат будет NULL.
  • 📌 Условия оцениваются последовательно, и выполнение прекращается при первом совпадении (как в switch-case в других языках).

Пример простого использования:

ВЫБРАТЬ

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

ИНАЧЕ "Мелкий" КАК КатегорияСделки,

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

ИЗ

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

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

2. Сравнение с CASE в SQL: ключевые различия

Разработчики, пришедшие из SQL, часто пытаются использовать CASE WHEN в запросах , что приводит к ошибкам. Основные отличия:

ФункциональностьSQL (CASE WHEN)1С (КОГДА)
Синтаксис началаCASE WHEN Условие THENКОГДА Условие ТОГДА
Завершение условияENDНе требуется
Вложенные условияПоддерживаютсяПоддерживаются, но с ограничениями на глубину
NULL в ИНАЧЕЯвное указание NULLАвтоматически, если блок ИНАЧЕ отсутствует

Пример эквивалентного запроса в SQL и 1С:

-- SQL

SELECT

CASE WHEN Price > 1000 THEN 'Expensive'

WHEN Price > 500 THEN 'Medium'

ELSE 'Cheap' END AS PriceCategory

FROM Products

-- 1С

ВЫБРАТЬ

КОГДА Цена > 1000 ТОГДА "Дорогой"

КОГДА Цена > 500 ТОГДА "Средний"

ИНАЧЕ "Дешёвый" КАК КатегорияЦены

ИЗ

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

Важное замечание: в нельзя использовать CASE как выражение в ORDER BY или GROUP BY без предварительного присвоения псевдонима в SELECT. В SQL такое ограничение отсутствует.

📊 Какой синтаксис вам удобнее?
CASE WHEN (SQL)
КОГДА (1С)
Оба одинаково
Затрудняюсь ответить

3. Работа с типами данных: даты, числа, строки

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

Правила приведения типов в условиях:

  • 📅 Даты: Сравниваются как даты, но при операции с числами преобразуются в количество дней с 01.01.0001.
  • 🔢 Числа: Автоматически приводятся к числовому типу, но строки вроде "100" не преобразуются в число.
  • 📜 Строки: Сравнение регистрозависимое (в отличие от оператора ПОДОБНО).

Примеры корректного сравнения:

-- Сравнение дат

ВЫБРАТЬ

КОГДА ДатаДокумента >= ДАТАВРЕМЯ(2023, 1, 1) ТОГДА "Актуальный"

ИНАЧЕ "Устаревший" КАК Статус

-- Сравнение чисел со строками (требуется явное приведение)

ВЫБРАТЬ

КОГДА ЧИСЛО(Код) > 1000 ТОГДА "Большой код"

ИНАЧЕ "Маленький код" КАК КатегорияКода

⚠️ Внимание: При сравнении полей типа Булево используйте явные значения ИСТИНА/ЛОЖЬ, а не 1/0. В противном случае условие КОГДА ПометкаУдаления = 1 не сработает корректно.
Что будет если сравнить дату и строку?

При неявном сравнении даты и строки (например, КОГДА ДатаДокумента = "01.01.2023") 1С попытается преобразовать строку в дату по текущим региональным настройкам. Если формат строки не совпадёт с системным (например, в системе установлен формат ММ.ДД.ГГГГ, а в строке ДД.ММ.ГГГГ), условие вернёт ЛОЖЬ даже при визуальном совпадении дат.

4. Вложенные условия и оптимизация производительности

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

  1. 🔍 Порядок условий: Размещайте наиболее вероятные условия в начале — это ускорит выход из конструкции.
  2. 🧹 Избегайте дублирования: Если одно условие проверяется несколько раз, вынесите его в отдельное выражение с ВЫРАЗИТЬ.
  3. 📊 Агрегатные функции: Не используйте СУММА() или КОЛИЧЕСТВО() внутри КОГДА — это приведёт к полному сканированию таблицы.

Пример оптимизированного вложенного условия:

ВЫБРАТЬ

КОГДА ВидДокумента = ЗНАЧЕНИЕ(Справочник.ВидыДокументов.ЗаказПокупателя)

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

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

КОГДА ВидДокумента = ЗНАЧЕНИЕ(Справочник.ВидыДокументов.Реализация)

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

ИНАЧЕ "Прочее" КАК ТипОперации

Для сложных условий (более 5-7 проверок) рассмотрите возможность:

  • 🔄 Вынесения логики в виртуальную таблицу.
  • 📝 Использования временных таблиц с предварительной категоризацией.

☑️ Проверка оптимизации запроса с КОГДА

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

5. Типичные ошибки и как их избежать

Даже опытные разработчики допускают ошибки при работе с КОГДА. Рассмотрим топ-5 проблем:

  1. 🚫 Пропущенное ТОГДА: Забыв указать ТОГДА, получите синтаксическую ошибку. Пример ошибочного кода:
    КОГДА Сумма > 1000 "Большая" -- Ошибка!
  2. 🔄 Неявное приведение типов: Сравнение КОГДА Дата = 0 не имеет смысла — дата никогда не будет равна числу.
  3. 📝 Длинные строки в результатах: Если в ТОГДА указать строку длиной > 255 символов, запрос упадёт с ошибкой переполнения.
  4. 🔢 NULL в условиях: Условие КОГДА Поле = NULL не сработает — нужно использовать ЕСТЬ NULL.
  5. 🔍 Логические ошибки: В конструкции ниже второй КОГДА никогда не выполнится:
    КОГДА Сумма > 100 ТОГДА "Больше 100"
    

    КОГДА Сумма > 50 ТОГДА "Больше 50" -- Недостижимо!

Для отладки сложных условий используйте:

  • 🛠️ Консоль запросов в конфигураторе с выводом плана выполнения.
  • 📋 Пошаговое тестирование: Проверяйте каждое условие отдельно.
⚠️ Внимание: В платформе 1С:Предприятие 8.3.20+ появилась возможность использовать ВЫРАЗИТЬ(КОГДА ...) как отдельное выражение в ГДЕ или УПОРЯДОЧИТЬ ПО. В более ранних версиях это приводило к ошибке.

6. Практическое применение: категоризация и трансформация данных

Конструкция КОГДА незаменима для:

  • 📊 Категоризации: Разделение клиентов по сегментам, товаров по ценовым группам.
  • 🔄 Трансформации данных: Замена кодов на наименования, конвертация единиц измерения.
  • 📅 Аналитики по периодам: Определение кварталов, сезонов, временных интервалов.

Пример категоризации клиентов по сумме покупок:

ВЫБРАТЬ

Клиент,

СУММА(СуммаДокумента) КАК ОбщаяСумма,

КОГДА СУММА(СуммаДокумента) > 1000000 ТОГДА "VIP"

КОГДА СУММА(СуммаДокумента) > 500000 ТОГДА "Премиум"

КОГДА СУММА(СуммаДокумента) > 100000 ТОГДА "Стандарт"

ИНАЧЕ "Новый" КАК КатегорияКлиента

ИЗ

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

ГДЕ

Реализация.Клиент В (&СписокКлиентов)

СГРУППИРОВАТЬ ПО

Клиент

Для трансформации данных часто комбинируют КОГДА с функциями:

  • 🔢 ЗНАЧЕНИЕ() — для сравнения со справочниками.
  • 📅 НАЧАЛОПЕРИОДА() — для работы с датами.
  • 📊 ВЫБОР() — как альтернатива для простых замен.
💡

Для ускорения запросов с категоризацией создайте предварительно заполненный справочник категорий и используйте соединение (ЛЕВОЕ СОЕДИНЕНИЕ) вместо вычисления КОГДА на лету.

7. Альтернативные подходы: когда КОГДА не оптимально

В некоторых случаях КОГДА уступает другим методам:

ЗадачаАльтернативаКогда использовать
Простая замена значенийВЫБОР()Если условий не больше 3-4
Фильтрация данныхГДЕ с логическими операторамиЕсли нужно только отобрать записи, а не трансформировать
Сложная логикаВиртуальные таблицы или временные таблицыЕсли условий больше 10 или они динамические
Работа с иерархиейПУТЬ() или УРОВЕНЬ()Для справочников с иерархией

Пример замены КОГДА на ВЫБОР():

-- Через КОГДА

ВЫБРАТЬ КОГДА Статус = 1 ТОГДА "Новый" ИНАЧЕ "Закрытый" КАК СтатусТекст

-- Через ВЫБОР (короче и быстрее)

ВЫБРАТЬ ВЫБОР(Статус, "Новый", "Закрытый") КАК СтатусТекст

Для динамических условий (например, когда список категорий хранится в справочнике) лучше использовать соединение:

ВЫБРАТЬ

Товар.Наименование,

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

ИЗ

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

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

ПО Товар.Категория = Категории.Ссылка

💡

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

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

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

Да, но только в платформе 1С:Предприятие 8.3.20 и выше. Пример:

ВЫБРАТЬ

Наименование

ИЗ

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

ГДЕ

ВЫРАЗИТЬ(КОГДА Цена > 1000 ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ) = ИСТИНА

В более ранних версиях это приведёт к ошибке.

Как сравнить несколько полей в одном КОГДА?

Используйте логические операторы И/ИЛИ внутри условия:

ВЫБРАТЬ

КОГДА (Дата >= &НачалоПериода И Дата <= &КонецПериода) И Сумма > 1000

ТОГДА "Актуальный крупный заказ"

ИНАЧЕ "Прочее" КАК Категория

Почему условие КОГДА Поле = NULL не работает?

В языке запросов для проверки на NULL используется оператор ЕСТЬ NULL:

ВЫБРАТЬ

КОГДА Поле ЕСТЬ NULL ТОГДА "Пустое"

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

Можно ли использовать КОГДА с агрегатными функциями?

Технически можно, но это неэффективно. Пример:

ВЫБРАТЬ

КОГДА СУММА(Количество) > 100 ТОГДА "Много"

ИНАЧЕ "Мало" КАК Итог

ИЗ

Документ.ПоступлениеТоваров

Такой запрос выполнит полное сканирование таблицы. Лучше использовать ГРУППИРОВКА с HAVING.

Как отладить сложный запрос с вложенными КОГДА?

Разбейте запрос на части:

  1. Проверьте каждое условие отдельно в консоли запросов.
  2. Используйте ПОМЕСТИТЬ для сохранения промежуточных результатов.
  3. Включите вывод плана выполнения (ОБЪЯСНИТЬ).

Пример с ПОМЕСТИТЬ:

ПОМЕСТИТЬ ВТ_Промежуточный

ВЫБРАТЬ

КОГДА Сумма > 1000 ТОГДА "Большой" ИНАЧЕ "Маленький" КАК Размер

ИЗ

Документ.Заказы;

ВЫБРАТЬ *

ИЗ

ВТ_Промежуточный