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

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

Мы рассмотрим не только базовый синтаксис, но и практические кейсы: от простой классификации данных до динамического формирования полей в отчётах. А в конце — разберём реальные примеры оптимизации запросов, где замена нескольких объединений таблиц на одно условие ВЫБОР КОГДА сократила время выполнения с 30 секунд до 0.5.

Как работает конструкция ВЫБОР КОГДА ТОГДА в 1С

Начнём с основ: синтаксис конструкции максимально приближен к человеческой логике. Она состоит из трёх обязательных частей:

1. ВЫБОР — начало конструкции (аналог CASE в SQL).

2. КОГДА [условие] ТОГДА [значение] — пара "условие-результат", которую можно повторять многократно.

3. ИНАЧЕ [значение_по_умолчанию] — необязательный блок для случаев, когда ни одно условие не сработало.

Простейший пример:

```sql

ВЫБРАТЬ

ВЫБОР

КОГДА СуммаДокумента > 100000 ТОГДА "Крупная сделка"

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

ИНАЧЕ "Мелкая сделка"

КОНЕЦ КАК КатегорияСделки,

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

ИЗ

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

```

Здесь для каждой строки таблицы РеализацияТоваровУслуг будет определена категория сделки на основе суммы документа. Важно: условия проверяются по порядку, и как только находит первое истинное — дальнейшие условия игнорируются.

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

Конструкция поддерживает:

  • 📌 Простые условия с операторами сравнения (=, >, <, <> и др.)
  • 📌 Логические операторы (И, ИЛИ, НЕ)
  • 📌 Вложенные конструкции ВЫБОР КОГДА (до 10 уровней вложенности в современных версиях платформы)
  • 📌 Вызов функций (например, НАЧИНАЕТСЯСТРОКОЙ(Наименование, "А"))
  • 📌 Работу с агрегатными функциями (СУММА, МАКСИМУМ и др.)
📊 Как часто вы используете ВЫБОР КОГДА в запросах 1С?
Постоянно, в каждом отчёте
Иногда, для сложной логики
Редеко, предпочитаю обрабатывать данные на клиенте
Никогда не использовал

Синтаксические особенности и скрытые возможности

Многие разработчики ограничиваются базовым применением конструкции, но у неё есть ряд нюансов, которые могут значительно упростить код:

1. Использование в вычисляемых полях

Конструкцию можно применять не только для классификации данных, но и для вычислений. Например, расчёт бонусов по сложной шкале:

```sql

ВЫБОР

КОГДА ОбъемПродаж > 1000000 ТОГДА ОбъемПродаж * 0.1

КОГДА ОбъемПродаж > 500000 ТОГДА ОбъемПродаж * 0.05

ИНАЧЕ 0

КОНЕЦ КАК Бонус

```

2. Работа с NULL

Особое внимание требует сравнение с NULL. Операторы = или <> с NULL всегда возвращают ЛОЖЬ. Для проверки на пустое значение используйте функцию ЗНАЧЕНИЕЗАПОЛНЕНО():

```sql

ВЫБОР

КОГДА НЕ ЗНАЧЕНИЕЗАПОЛНЕНО(ДатаОплаты) ТОГДА "Не оплачено"

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

КОНЕЦ КАК СтатусОплаты

```

3. Упрощённая форма (без условий)

Редко используемый, но полезный вариант — когда условие заменяется на значение, а сравнение идёт с выражением перед ВЫБОР:

```sql

ВЫБРАТЬ

ТипДокумента КАК КодТипа,

ВЫБОР ТипДокумента

КОГДА "ЗаказПокупателя" ТОГДА "Заказ"

КОГДА "РеализацияТоваровУслуг" ТОГДА "Продажа"

ИНАЧЕ "Прочее"

КОНЕЦ КАК ТипДокументаОписание

ИЗ

Документ.ЛюбойДокумент

```

Это удобно для замены кодов на человекочитаемые значения.

💡

Если в условии нужно проверить принадлежность значения к списку, используйте оператор В() вместо множества ИЛИ. Например: КОГДА ТипДокумента В ("Заказ", "Счёт") ТОГДА "Продажи"

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

Даже опытные разработчики иногда допускают ошибки при работе с ВЫБОР КОГДА. Вот наиболее распространённые проблемы и способы их решения:

1. Порядок условий имеет значение

Конструкция проверяет условия сверху вниз и возвращает результат при первом совпадении. Классическая ошибка — размещать более общее условие выше частного:

```sql

-- НЕПРАВИЛЬНО: условие "Сумма > 0" перехватит все случаи

ВЫБОР

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

КОГДА Сумма > 100000 ТОГДА "Крупная" -- Это условие никогда не сработает!

КОНЕЦ

-- ПРАВИЛЬНО: от частного к общему

ВЫБОР

КОГДА Сумма > 100000 ТОГДА "Крупная"

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

КОНЕЦ

```

2. Избыточные условия

Часто встречаются запросы, где в каждом условии повторяется одна и та же проверка:

```sql

-- НЕОПТИМАЛЬНО

ВЫБОР

КОГДА ТипДокумента = "Заказ" И Статус = "Проводён" ТОГДА "Проводённый заказ"

КОГДА ТипДокумента = "Заказ" И Статус = "Не проводён" ТОГДА "Непроводённый заказ"

КОГДА ТипДокумента = "Реализация" И Статус = "Проводён" ТОГДА "Проводённая реализация"

КОНЕЦ

-- ОПТИМАЛЬНО: вынести общую часть в отдельное поле

ВЫБОР ТипДокумента

КОГДА "Заказ" ТОГДА

ВЫБОР Статус

КОГДА "Проводён" ТОГДА "Проводённый заказ"

КОГДА "Не проводён" ТОГДА "Непроводённый заказ"

КОНЕЦ

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

ВЫБОР Статус

КОГДА "Проводён" ТОГДА "Проводённая реализация"

КОНЕЦ

КОНЕЦ

```

3. Забытый блок ИНАЧЕ

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

⚠️ Внимание: В версиях платформы ниже 8.3.10 вложенные конструкции ВЫБОР КОГДА (глубже 3 уровней) могли приводить к ошибкам компиляции запроса. Проверяйте совместимость, если поддерживаете старые релизы.

Правильный порядок условий (от частного к общему)|

Все возможные случаи покрыты (есть блок ИНАЧЕ)|

Нет избыточных проверок одних и тех же полей|

Учтена работа с NULL (используется ЗНАЧЕНИЕЗАПОЛНЕНО)|

-->

Примеры практического применения

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

1. Классификация клиентов по ABC/XYZ-анализу

Допустим, нужно разделить клиентов на категории по объёму продаж и частоте заказов:

```sql

ВЫБРАТЬ

Клиент,

СУММА(СуммаДокумента) КАК ОбъемПродаж,

КОЛИЧЕСТВО(*) КАК КоличествоЗаказов,

ВЫБОР

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

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

ИНАЧЕ "C"

КОНЕЦ КАК КатегорияABC,

ВЫБОР

КОГДА КОЛИЧЕСТВО(*) > 20 ТОГДА "X"

КОГДА КОЛИЧЕСТВО(*) > 5 ТОГДА "Y"

ИНАЧЕ "Z"

КОНЕЦ КАК КатегорияXYZ

ИЗ

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

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

Клиент

```

2. Динамическое формирование наименований в отчёте

Когда нужно вывести разные поля в зависимости от типа документа:

```sql

ВЫБРАТЬ

ВЫБОР

КОГДА ТипДокумента = "ЗаказПокупателя" ТОГДА Номенклатура.Наименование

КОГДА ТипДокумента = "ВозвратТоваровОтПокупателя" ТОГДА "Возврат: " + Номенклатура.Наименование

ИНАЧЕ ТипДокумента + ": " + Номенклатура.Наименование

КОНЕЦ КАК НаименованиеДляОтчёта,

Количество,

Сумма

ИЗ

Документ.ЛюбойДокумент КАК Документ

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

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

```

3. Расчёт скидок по сложным правилам

Когда скидка зависит от нескольких параметров (например, типа клиента и суммы заказа):

```sql

ВЫБРАТЬ

Клиент,

СУММА(СуммаДокумента) КАК СуммаЗаказов,

ВЫБОР

КОГДА Клиент.ТипКлиента = "Оптовый" И СУММА(СуммаДокумента) > 50000 ТОГДА 0.15

КОГДА Клиент.ТипКлиента = "Оптовый" ТОГДА 0.10

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

ИНАЧЕ 0

КОНЕЦ КАК МаксимальнаяСкидка

ИЗ

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

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

ПО Заказ.Контрагент = Клиент.Ссылка

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

Клиент

```

Как ускорить запрос с множеством условий?

Если в запросе используется более 10 условий в конструкции ВЫБОР КОГДА, рассмотрите возможность:

1. Перенести логику в виртуальную таблицу (если условия зависят от одного поля).

2. Использовать временную таблицу для предварительной классификации данных.

3. Разбить запрос на несколько более простых и объединить результаты с помощью ОБЪЕДИНИТЬ ВСЕ.

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

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

1. Индексы и условия

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

```sql

ВЫБОР

КОГДА ДатаДокумента > &ТекущаяДата ТОГДА "Будущий"

КОГДА ДатаДокумента = &ТекущаяДата ТОГДА "Текущий"

ИНАЧЕ "Прошлый"

КОНЕЦ

```

будет работать быстрее, если по полю ДатаДокумента есть индекс.

2. Избегайте вычислений в условиях

Вынесение вычислений из условий в отдельные поля может ускорить запрос в разы:

```sql

-- МЕДЛЕННО

ВЫБОР

КОГДА (Количество * Цена) > 10000 ТОГДА "Крупная позиция"

ИНАЧЕ "Мелкая позиция"

КОНЕЦ

-- БЫСТРО

ВЫБОР

КОГДА СуммаПозиции > 10000 ТОГДА "Крупная позиция"

ИНАЧЕ "Мелкая позиция"

КОНЕЦ

-- где СуммаПозиции — вычисляемое поле (Количество * Цена)

```

3. Ограничивайте количество условий

Каждое дополнительное условие увеличивает время выполнения. Если условий больше 7-10, стоит рассмотреть альтернативные подходы (например, предварительную классификацию данных во временной таблице).

Подход Количество условий Время выполнения (мс) Рекомендация
Прямое использование ВЫБОР КОГДА 1-5 10-50 Оптимально
Прямое использование ВЫБОР КОГДА 5-10 50-200 Приемлемо, но проверьте индексы
Прямое использование ВЫБОР КОГДА 10+ 200+ Рассмотрите альтернативы
Временная таблица с классификацией 100+ 10-30 Лучший выбор для сложной логики
💡

Если запрос с ВЫБОР КОГДА выполняется дольше 1 секунды — это повод для оптимизации. Начните с проверки индексов и вынесения вычислений в отдельные поля.

Альтернативные подходы: когда ВЫБОР КОГДА не подходит

В некоторых случаях использование ВЫБОР КОГДА может быть неоптимальным. Рассмотрим альтернативы:

1. Объединение таблиц (СОЕДИНЕНИЕ)

Если условия зависят от данных из других таблиц, иногда эффективнее использовать соединения. Например, вместо:

```sql

ВЫБОР

КОГДА Клиент.ТипКлиента = "Оптовый" ТОГДА "Опт"

КОГДА Клиент.ТипКлиента = "Розничный" ТОГДА "Розница"

КОНЕЦ

```

можно сделать:

```sql

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

ПО Клиент.ТипКлиента = ТипКлиента.Ссылка

```

и вывести ТипКлиента.Наименование.

2. Виртуальные таблицы

Для сложной аналитики (например, ABC/XYZ-анализа) удобнее использовать виртуальные таблицы регистров накопления, где классификация уже выполнена на уровне платформы.

3. Обработка на клиенте

Если логика слишком сложна или зависит от пользовательских настроек, иногда проще получить "сырые" данные запросом, а классификацию сделать в модуле отчёта.

⚠️ Внимание: В версиях платформы 8.3.15+ появилась поддержка оконных функций (например, РАЗДЕЛИТЬ НА ГРУППЫ), которые могут заменить часть сценариев с ВЫБОР КОГДА для аналитических задач.

Частые вопросы и ответы

Можно ли использовать ВЫБОР КОГДА в условии WHERE?

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

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

ВЫБРАТЬ

Номенклатура

ИЗ

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

ГДЕ

ВЫБОР

КОГДА Сумма > 1000 ТОГДА ИСТИНА -- Так делать НЕЛЬЗЯ!

КОНЕЦ

Правильный вариант:

ВЫБРАТЬ

Номенклатура

ИЗ

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

ГДЕ

Сумма > 1000

Как сделать вложенный ВЫБОР КОГДА?

Вложенные конструкции поддерживаются и позволяют реализовывать сложную логику. Главное — следить за читаемостью кода. Пример:

ВЫБРАТЬ

ВЫБОР

КОГДА ТипДокумента = "Заказ" ТОГДА

ВЫБОР Статус

КОГДА "Проводён" ТОГДА "Проводённый заказ"

КОГДА "Отменён" ТОГДА "Отменённый заказ"

ИНАЧЕ "Черновик заказа"

КОНЕЦ

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

ВЫБОР Статус

КОГДА "Проводён" ТОГДА "Проводённая реализация"

КОНЕЦ

ИНАЧЕ "Другой документ"

КОНЕЦ КАК ОписаниеДокумента

ИЗ

Документ.ЛюбойДокумент

Ограничение: глубина вложенности зависит от версии платформы (в 8.3.16+ поддерживается до 10 уровней).

Почему запрос с ВЫБОР КОГДА работает медленно?

Основные причины:

  1. Отсутствуют индексы по полям, используемым в условиях.
  2. Слишком много условий (более 10) без группировки.
  3. В условиях выполняются сложные вычисления (например, ВЫРАЗИТЬ(Дата КАК Строка)).
  4. Конструкция используется в подзапросах или соединениях.

Решения:

  • 🔹 Добавьте индексы по полям в условиях.
  • 🔹 Вынесите вычисления в отдельные поля.
  • 🔹 Разбейте запрос на части с использованием временных таблиц.
  • 🔹 Замените часть логики на соединения с справочниками.
Можно ли использовать ВЫБОР КОГДА с агрегатными функциями?

Да, конструкция отлично работает с СУММА, КОЛИЧЕСТВО, МАКСИМУМ и другими агрегатными функциями. Пример:

ВЫБРАТЬ

Контрагент,

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

ВЫБОР

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

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

ИНАЧЕ "Стандарт"

КОНЕЦ КАК КатегорияКлиента

ИЗ

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

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

Контрагент

Важно: агрегатные функции внутри ВЫБОР КОГДА должны соответствовать уровню группировки запроса.

Как обработать NULL в условиях?

Для проверки на NULL используйте функцию ЗНАЧЕНИЕЗАПОЛНЕНО(). Примеры:

-- Проверка на NULL

ВЫБОР

КОГДА НЕ ЗНАЧЕНИЕЗАПОЛНЕНО(ДатаОплаты) ТОГДА "Не оплачено"

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

КОНЕЦ

-- Проверка на НЕ NULL

ВЫБОР

КОГДА ЗНАЧЕНИЕЗАПОЛНЕНО(ПричинаОтмены) ТОГДА ПричинаОтмены

ИНАЧЕ "Причина не указана"

КОНЕЦ

Обратите внимание: операторы = NULL или <> NULL не работают — они всегда возвращают ЛОЖЬ.