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

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

Что такое множественный выбор в запросах 1С и зачем он нужен

Конструкция КОГДА ... ТОГДА ... ИНАЧЕ в языке запросов аналогична оператору CASE WHEN в SQL. Она позволяет динамически формировать значения полей в результате запроса на основе условий. Например, вместо того чтобы создавать несколько запросов или использовать сложные объединения, вы можете в одном запросе:

  • 📊 Классифицировать данные (например, разделить клиентов на группы по объёму заказов)
  • 🔄 Заменять значения (подставлять "Да"/"Нет" вместо ИСТИНА/ЛОЖЬ)
  • 📈 Вычислять производные поля (например, рассчитывать скидку в зависимости от категории товара)
  • 🔍 Фильтровать данные по сложным условиям без дополнительных соединений таблиц

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

📊 Как часто вы используете КОГДА в запросах 1С?
Постоянно, в большинстве запросов
Иногда, для специфических задач
Редеко, предпочитаю другие методы
Никогда не использовал

Синтаксис конструкции КОГДА в запросах 1С

Базовый синтаксис выглядит так:

ВЫБРАТЬ

КОГДА Условие1 ТОГДА Значение1

КОГДА Условие2 ТОГДА Значение2

...

ИНАЧЕ ЗначениеПоУмолчанию

КОНЕЦ КАК ПолеРезультата

Разберём ключевые элементы:

  • 🔹 КОГДА Условие ТОГДА Значение — пара "условие-результат". Условие может быть любым логическим выражением, поддерживаемым в запросах (сравнения, функции, подзапросы).
  • 🔹 ИНАЧЕ — необязательный блок, который срабатывает, если ни одно из условий не выполнено. Если его опустить, результат будет NULL.
  • 🔹 КАК ПолеРезультата — присваивает имя столбцу в результате запроса.

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

ВЫБРАТЬ

КОГДА Справочник.Клиенты.Категория = "VIP" ТОГДА "Приоритетный"

КОГДА Справочник.Клиенты.СуммаЗаказов > 100000 ТОГДА "Крупный"

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

КОНЕЦ КАК ТипКлиента,

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

ИЗ

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

💡

Если в условии КОГДА используете сравнение с NULL, используйте конструкцию ЗНАЧЕНИЕ ЗАПОЛНЕНО(), а не просто = NULL. Последнее не сработает корректно!

Практические примеры использования КОГДА

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

1. Категоризация данных

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

ВЫБРАТЬ

КОГДА ОстаткиТоваров.Количество = 0 ТОГДА "Нет в наличии"

КОГДА ОстаткиТоваров.Количество < 10 ТОГДА "Мало"

КОГДА ОстаткиТоваров.Количество >= 100 ТОГДА "Много"

ИНАЧЕ "Среднее количество"

КОНЕЦ КАК СтатусОстатка,

ОстаткиТоваров.Товар КАК Товар

ИЗ

РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров

2. Замена булевых значений на текст

Часто в отчётах требуется показывать не ИСТИНА/ЛОЖЬ, а "Да/Нет":

ВЫБРАТЬ

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

ИНАЧЕ "Нет"

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

Документ.ЗаказКлиента.Номер КАК НомерЗаказа

ИЗ

Документ.ЗаказКлиента КАК Документ.ЗаказКлиента

3. Расчёт скидок по условиям

Можно динамически назначать скидку в зависимости от суммы заказа:

ВЫБРАТЬ

КОГДА Документ.ЗаказКлиента.СуммаДокумента > 50000 ТОГДА 0.15

КОГДА Документ.ЗаказКлиента.СуммаДокумента > 20000 ТОГДА 0.10

КОГДА Документ.ЗаказКлиента.СуммаДокумента > 10000 ТОГДА 0.05

ИНАЧЕ 0

КОНЕЦ КАК РазмерСкидки,

Документ.ЗаказКлиента.Контрагент КАК Клиент

ИЗ

Документ.ЗаказКлиента КАК Документ.ЗаказКлиента

Как избежать ошибки "Тип не совпадает" в КОГДА

Если в разных ветках КОГДА возвращаются значения разных типов (например, строка и число), 1С выдаст ошибку. Все результаты должны быть приведёны к одному типу, например, с помощью СТРОКА() или ЧИСЛО().

Оптимизация запросов с КОГДА: что нужно знать

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

  1. 🚀 Избегайте сложных условий в КОГДА. Если условие включает подзапросы или функции (например, НАЙТИ()), запрос будет выполняться дольше. По возможности выносите такие проверки в отдельные соединения таблиц.
  2. 📉 Минимизируйте количество веток КОГДА. Чем их больше, тем сложнее план выполнения запроса. Если условий больше 5–7, рассмотрите альтернативные подходы.
  3. 🔄 Используйте индексируемые поля в условиях. Если в условии участвует поле, по которому нет индекса, СУБД будет сканировать всю таблицу.
  4. 📊 Тестируйте производительность. Для больших баз данных сравните время выполнения запроса с КОГДА и альтернативными методами (например, ОБЪЕДИНИТЬ).

Пример неоптимального запроса (сложное условие в каждой ветке):

ВЫБРАТЬ

КОГДА НАЙТИ(Документ.ЗаказКлиента.Комментарий, "Срочно") > 0 ТОГДА "Приоритет"

КОГДА Документ.ЗаказКлиента.Дата < ТЕКУЩАЯДАТА() - 30 ТОГДА "Просрочен"

ИНАЧЕ "Обычный"

КОНЕЦ КАК Статус

Оптимизированный вариант (предварительный расчёт в подзапросе):

ВЫБРАТЬ

КОГДА СрочныйЗаказ ТОГДА "Приоритет"

КОГДА ПросроченныйЗаказ ТОГДА "Просрочен"

ИНАЧЕ "Обычный"

КОНЕЦ КАК Статус

ИЗ (

ВЫБРАТЬ

НАЙТИ(Документ.ЗаказКлиента.Комментарий, "Срочно") > 0 КАК СрочныйЗаказ,

Документ.ЗаказКлиента.Дата < ТЕКУЩАЯДАТА() - 30 КАК ПросроченныйЗаказ

ИЗ

Документ.ЗаказКлиента КАК Документ.ЗаказКлиента

) КАК Подзапрос

💡

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

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

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

Ошибка Причина Как исправить
Ошибка типа "Тип не совпадает" В разных ветках КОГДА возвращаются значения разных типов (строка и число). Приведите все результаты к одному типу с помощью СТРОКА(), ЧИСЛО().
Запрос выполняется слишком долго Сложные условия в каждой ветке КОГДА или отсутствие индексов. Упростите условия или используйте соединения таблиц вместо КОГДА.
Некорректный результат для NULL Условие КОГДА Поле = NULL не срабатывает (в SQL сравнение с NULL всегда возвращает NULL). Используйте ЗНАЧЕНИЕ ЗАПОЛНЕНО(Поле).
Ошибка "Поле не найдено" В условии КОГДА используется поле, не включённое в ИЗ или СОЕДИНИТЬ. Проверьте наличие поля в источниках данных запроса.

Пример ошибки с NULL:

-- НЕПРАВИЛЬНО (не сработает для NULL):

ВЫБРАТЬ

КОГДА Справочник.Контрагенты.ИНН = NULL ТОГДА "Без ИНН"

ИНАЧЕ "С ИНН"

КОНЕЦ КАК СтатусИНН

-- ПРАВИЛЬНО:

ВЫБРАТЬ

КОГДА НЕ ЗНАЧЕНИЕ ЗАПОЛНЕНО(Справочник.Контрагенты.ИНН) ТОГДА "Без ИНН"

ИНАЧЕ "С ИНН"

КОНЕЦ КАК СтатусИНН

Все ветки КОГДА возвращают значения одного типа|Условия не содержат сравнений с NULL без ЗНАЧЕНИЕ ЗАПОЛНЕНО()|Поля в условиях существуют в источниках данных|Для больших таблиц проверены индексы-->

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

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

  • 🔀 ОБЪЕДИНИТЬ (UNION) — если данные нужно брать из разных таблиц или запросов. Например, для объединения остатков по нескольким складам.
  • 🔗 СОЕДИНИТЬ (JOIN) — если условия зависят от данных из связанных таблиц. Например, проверка статуса клиента из справочника.
  • 📝 Виртуальные таблицы — если логика слишком сложна для КОГДА, но нужны агрегированные данные (например, остатки с разрезами).
  • 🖥️ Обработка на стороне 1С — если условия динамические и зависят от пользовательского ввода, иногда проще получить данные запросом, а затем обработать их в коде.

Пример, где ОБЪЕДИНИТЬ эффективнее:

-- Вместо:

ВЫБРАТЬ

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

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

КОНЕЦ КАК Сумма

ИЗ (...)

-- Лучше:

ВЫБРАТЬ Документ.ЗаказКлиента.Сумма КАК Сумма

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

ОБЪЕДИНИТЬ

ВЫБРАТЬ Документ.Реализация.Сумма КАК Сумма

ИЗ Документ.Реализация КАК Документ.Реализация

💡

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

Расширенные возможности: вложенные КОГДА и работа с агрегатами

Конструкцию КОГДА можно вкладывать друг в друга, а также комбинировать с агрегатными функциями (СУММА, МАКСИМУМ и т. д.). Это позволяет решать сложные задачи в одном запросе.

1. Вложенные КОГДА

Пример: классификация клиентов по двум критериям (сумма заказов и регион):

ВЫБРАТЬ

КОГДА Справочник.Клиенты.Регион = "Москва"

ТОГДА КОГДА Справочник.Клиенты.СуммаЗаказов > 100000 ТОГДА "VIP Москва"

ИНАЧЕ "Стандарт Москва"

КОГДА Справочник.Клиенты.Регион = "Санкт-Петербург"

ТОГДА КОГДА Справочник.Клиенты.СуммаЗаказов > 50000 ТОГДА "VIP СПб"

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

ИНАЧЕ "Региональный клиент"

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

2. КОГДА с агрегатными функциями

Можно динамически рассчитывать показатели. Например, определить "лидера продаж" по категориям:

ВЫБРАТЬ

Номенклатура.Категория КАК Категория,

КОГДА СУММА(Документ.Реализация.Количество) > 1000 ТОГДА "Хит продаж"

КОГДА СУММА(Документ.Реализация.Количество) > 500 ТОГДА "Популярный"

ИНАЧЕ "Обычный"

КОНЕЦ КАК СтатусТовара

ИЗ

Документ.Реализация КАК Документ.Реализация

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

ПО Документ.Реализация.Номенклатура = Номенклатура.Ссылка

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

Номенклатура.Категория

Важно: при использовании КОГДА с агрегатами учитывайте, что:

  • 📌 Условия в КОГДА применяются после группировки, а не до неё.
  • 📌 Если в условии нужны данные до агрегации (например, проверка каждой строки), используйте подзапрос.
💡

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

FAQ: Ответы на частые вопросы о КОГДА в запросах 1С

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

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

ВЫБРАТЬ ...

ГДЕ Ссылка В (

ВЫБРАТЬ Ссылка

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

ГДЕ КОГДА Статус = "Оплачен" ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ

)

Но такой подход неэффективен — лучше переписать условие без КОГДА.

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

Используйте логические операторы И, ИЛИ внутри условия КОГДА:

ВЫБРАТЬ

КОГДА (Документ.ЗаказКлиента.Сумма > 10000)

И (Документ.ЗаказКлиента.Дата > '2023-01-01') ТОГДА "Крупный новый заказ"

ИНАЧЕ "Другой заказ"

КОНЕЦ КАК ТипЗаказа

Почему запрос с КОГДА работает медленно на большой базе?

Причины могут быть следующими:

  1. Отсутствуют индексы на полях, участвующих в условиях КОГДА.
  2. Условия содержат функции (например, НАЙТИ()), которые не могут использовать индексы.
  3. Слишком много веток КОГДА (оптимально — не более 5–7).
  4. В условиях используются подзапросы.

Решение: упростите условия, добавьте индексы или разбейте запрос на несколько этапов.

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

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

Пример с соединением:

ВЫБРАТЬ

КОГДА Справочник.Контрагенты.Категория = "VIP"

И Документ.ЗаказКлиента.Сумма > 10000 ТОГДА "Приоритетный VIP"

ИНАЧЕ "Обычный"

КОНЕЦ КАК ТипЗаказа

ИЗ

Документ.ЗаказКлиента КАК Документ.ЗаказКлиента

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

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

Как вернуть NULL в одной из веток КОГДА, если в других ветках возвращаются строки?

Нужно явно привести NULL к строковому типу с помощью ЗНАЧЕНИЕ(NULL) или СТРОКА(NULL), иначе будет ошибка типов:

ВЫБРАТЬ

КОГДА Условие1 ТОГДА "Значение1"

КОГДА Условие2 ТОГДА ЗНАЧЕНИЕ(NULL) -- Явное приведение к строке

ИНАЧЕ "Значение3"

КОНЕЦ КАК Результат