ВЫБОР КОГДА ТОГДА ИНАЧЕ КОНЕЦ: условные выражения в языке запросов 1С 8.3
Содержание
Конструкция ВЫБОР КОГДА … ТОГДА … ИНАЧЕ … КОНЕЦ в 1С — это условное выражение языка запросов, аналог CASE WHEN из SQL. Она вычисляет значение поля по условию прямо в запросе: «если сумма больше 100 000 — “Крупная сделка”, иначе — “Обычная”». Работает в запросах, в системе компоновки данных (СКД) и в выражениях вычисляемых полей.
Главная ловушка для новичка: во встроенном языке модулей оператора Выбор-Когда нет. Если написать его в общем модуле или в форме, получите синтаксическую ошибку. В коде ту же задачу решают через Если … ИначеЕсли … КонецЕсли, тернарный оператор ?() или Соответствие. Ниже — синтаксис, рабочие примеры, ошибки и замена для кода.
Синтаксис ВЫБОР КОГДА в запросе 1С
Общая форма выражения:
ВЫБОР
КОГДА <Условие1> ТОГДА <Значение1>
КОГДА <Условие2> ТОГДА <Значение2>
...
ИНАЧЕ <ЗначениеПоУмолчанию>
КОНЕЦ
Английский вариант — CASE WHEN … THEN … ELSE … END. Оба написания равноправны, регистр букв не важен.
Правила, которые стоит держать в голове:
- 🔹 Веток КОГДА может быть сколько угодно, минимум одна.
- 🔹 Условия проверяются сверху вниз. Сработает первая ветка, где условие истинно, остальные игнорируются.
- 🔹 ИНАЧЕ необязательна. Если её нет и ни одно условие не сработало, результат —
NULL. - 🔹 КОНЕЦ обязателен. Без него запрос не разберётся.
- 🔹 Псевдоним ставят после КОНЕЦ:
КОНЕЦ КАК Категория. Без псевдонима поле получит имя видаПоле1. - 🔹 В языке запросов 1С есть только форма с условиями. Короткой записи SQL
CASE Поле WHEN 1 THEN …нет: каждое КОГДА содержит полное логическое выражение.
Что можно писать в условии и в значении
В условии после КОГДА допустимо любое логическое выражение языка запросов:
| Операция | Пример условия |
|---|---|
| Сравнение | Остаток > 0, Дата >= &НачалоПериода |
| Логика | Проведен И НЕ ПометкаУдаления |
| Список значений | Склад В (&СписокСкладов) |
| Диапазон | Сумма МЕЖДУ 1000 И 5000 |
| Шаблон строки | Наименование ПОДОБНО "%ООО%" |
| Проверка NULL | Цена ЕСТЬ NULL |
| Тип ссылки | Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг |
После ТОГДА и ИНАЧЕ ставят значение: поле, литерал, параметр, арифметику, функцию или ещё один ВЫБОР. Литералы пишут так: строки — "Текст", числа — 100, логические — ИСТИНА/ЛОЖЬ, даты — ДАТАВРЕМЯ(2025, 1, 1), ссылки — ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка).
Где в запросе допускается ВЫБОР
- ✅ в списке полей
ВЫБРАТЬ— самый частый случай; - ✅ внутри агрегатных функций:
СУММА(ВЫБОР … КОНЕЦ); - ✅ в
ГДЕ,ИМЕЮЩИЕ, условии соединенияПО; - ✅ в
СГРУППИРОВАТЬ ПОиУПОРЯДОЧИТЬ ПО; - ✅ вложенным в другой ВЫБОР.
Выбор Когда или Если Тогда: что где работает
Путаница возникает из-за того, что в 1С два языка: язык запросов и встроенный язык модулей. У каждого свой условный оператор.
| Где пишете | Что использовать | Пример |
|---|---|---|
| Текст запроса | ВЫБОР КОГДА … КОНЕЦ | ВЫБОР КОГДА Сумма > 0 ТОГДА "Долг" ИНАЧЕ "Нет" КОНЕЦ |
| Вычисляемое поле или ресурс СКД | Выбор Когда … Конец | то же выражение |
| Модуль (форма, объект, общий) | Если … ИначеЕсли … КонецЕсли | многоветочная логика |
| Модуль, одно условие | ?(Условие, Знач1, Знач2) | Текст = ?(Сумма > 0, "Долг", "Нет"); |
| Модуль, выбор по значению | Соответствие | таблица «код → значение» |
Когда условие удобнее посчитать в запросе:
- 📊 значение нужно для группировки, сортировки или итогов;
- 📊 строк много, и обходить их циклом в коде дольше;
- 📊 результат идёт в отчёт СКД, где нет места для кода.
Когда лучше в коде модуля:
- 🧩 логика вызывает функции общих модулей или читает настройки;
- 🧩 нужно сообщение пользователю, запись в журнал или исключение;
- 🧩 условие зависит от значений, которых нет в базе.
Примеры конструкции Выбор-Когда в запросах 1С
Примеры написаны для типовой «Бухгалтерии предприятия 3.0». Имена объектов в других конфигурациях могут отличаться, сама конструкция — одна для всех.
Пример 1. Подпись вместо значения перечисления
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
ВЫБОР
КОГДА Контрагенты.ЮридическоеФизическоеЛицо = ЗНАЧЕНИЕ(Перечисление.ЮридическоеФизическоеЛицо.ЮридическоеЛицо)
ТОГДА "Организация"
КОГДА Контрагенты.ЮридическоеФизическоеЛицо = ЗНАЧЕНИЕ(Перечисление.ЮридическоеФизическоеЛицо.ФизическоеЛицо)
ТОГДА "Физлицо или ИП"
ИНАЧЕ "Не заполнено"
КОНЕЦ КАК ВидКонтрагента
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
НЕ Контрагенты.ЭтоГруппа
Ветка ИНАЧЕ ловит пустое значение перечисления. Без неё в колонке были бы NULL.
Пример 2. Разбивка суммы по диапазонам
Задача: разложить продажи по группам «до 10 тыс.», «10–100 тыс.», «свыше 100 тыс.».
ВЫБРАТЬ
Реализация.Ссылка КАК Документ,
Реализация.СуммаДокумента КАК Сумма,
ВЫБОР
КОГДА Реализация.СуммаДокумента > 100000 ТОГДА "3. Свыше 100 тыс."
КОГДА Реализация.СуммаДокумента > 10000 ТОГДА "2. 10–100 тыс."
ИНАЧЕ "1. До 10 тыс."
КОНЕЦ КАК Группа
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Проведен
И Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
Порядок веток здесь решает всё. Документ на 150 000 подходит под оба первых условия, но попадёт в «Свыше 100 тыс.», потому что эта ветка стоит выше. Поменяйте ветки местами — и крупные сделки «утекут» в среднюю группу.
Номер в начале подписи («1.», «2.», «3.») — простой способ получить правильный порядок групп при сортировке по строке.
Пример 3. Сводная таблица по месяцам в одном запросе
ВЫБОР внутри СУММА разворачивает строки в колонки. Один проход по таблице вместо двенадцати отдельных запросов:
ВЫБРАТЬ
Реализация.Контрагент КАК Контрагент,
СУММА(ВЫБОР КОГДА МЕСЯЦ(Реализация.Дата) = 1 ТОГДА Реализация.СуммаДокумента ИНАЧЕ 0 КОНЕЦ) КАК Январь,
СУММА(ВЫБОР КОГДА МЕСЯЦ(Реализация.Дата) = 2 ТОГДА Реализация.СуммаДокумента ИНАЧЕ 0 КОНЕЦ) КАК Февраль,
СУММА(ВЫБОР КОГДА МЕСЯЦ(Реализация.Дата) = 3 ТОГДА Реализация.СуммаДокумента ИНАЧЕ 0 КОНЕЦ) КАК Март
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Проведен
И ГОД(Реализация.Дата) = &Год
СГРУППИРОВАТЬ ПО
Реализация.Контрагент
ИНАЧЕ 0 здесь нужен. Без него у контрагента без продаж в марте в колонке будет NULL, а не ноль. При выводе в табличный документ это пустая ячейка, а при сложении в коде — ошибка или неверный итог.
Пример 4. Своя сортировка
Нужно вывести сначала просроченные заказы, потом сегодняшние, потом остальные:
УПОРЯДОЧИТЬ ПО
ВЫБОР
КОГДА Заказы.ДатаОтгрузки < &Сегодня ТОГДА 1
КОГДА Заказы.ДатаОтгрузки = &Сегодня ТОГДА 2
ИНАЧЕ 3
КОНЕЦ,
Заказы.ДатаОтгрузки
Числовой ключ сортировки не обязательно выводить в результат: выражение живёт только в УПОРЯДОЧИТЬ ПО.
Пример 5. Вложенный ВЫБОР
ВЫБОР
КОГДА Остатки.КоличествоОстаток <= 0 ТОГДА "Нет в наличии"
ИНАЧЕ
ВЫБОР
КОГДА Остатки.КоличествоОстаток < 10 ТОГДА "Мало"
ИНАЧЕ "Достаточно"
КОНЕЦ
КОНЕЦ КАК Наличие
Вложенность допустима, но два уровня — разумный предел. Тот же результат чаще проще записать плоско, тремя ветками КОГДА.
Ссылки, NULL и составные типы внутри ВЫБОР
Проверка типа регистратора
Поле Регистратор у регистров составного типа: в нём лежат ссылки на разные документы. Оператор ССЫЛКА проверяет, какой именно:
ВЫБОР
КОГДА Движения.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг ТОГДА "Приход"
КОГДА Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг ТОГДА "Расход"
ИНАЧЕ "Прочее"
КОНЕЦ КАК ВидДвижения
Чтобы взять реквизит конкретного документа, приведите тип через ВЫРАЗИТЬ:
ВЫБОР
КОГДА Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
ТОГДА ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент
ИНАЧЕ НЕОПРЕДЕЛЕНО
КОНЕЦ КАК Контрагент
Обращение Регистратор.Контрагент без ВЫРАЗИТЬ заставит платформу соединить таблицы всех документов-регистраторов. На большом регистре это заметно тормозит запрос.
NULL после левого соединения
После ЛЕВОЕ СОЕДИНЕНИЕ поля правой таблицы бывают NULL. Сравнение = NULL никогда не даёт истину — проверяют только через ЕСТЬ NULL:
ВЫБОР
КОГДА Цены.Цена ЕСТЬ NULL ТОГДА "Цена не задана"
ИНАЧЕ "Есть цена"
КОНЕЦ
Если нужно просто подставить значение вместо NULL, короче функция ЕСТЬNULL(Цены.Цена, 0). ВЫБОР оставьте для случаев, когда нужна ещё и другая логика.
Пустые ссылки и пустые даты
Пустая ссылка и NULL — разные вещи. Незаполненный реквизит хранит пустую ссылку, а не NULL:
- 🔸 пустая ссылка:
КОГДА Документ.Склад = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка) ТОГДА …; - 🔸 пустая дата:
КОГДА Документ.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1) ТОГДА …; - 🔸 пустое значение перечисления:
ЗНАЧЕНИЕ(Перечисление.<Имя>.ПустаяСсылка).
Тип результата
Если ветки возвращают значения разных типов (в одной строка, в другой число), колонка станет составного типа. В отчёте это проявится странной сортировкой и проблемами при сложении. Держите все ветки в одном типе, а при необходимости приводите явно: ВЫРАЗИТЬ(… КАК ЧИСЛО(15, 2)).
Выбор-Когда в системе компоновки данных
В СКД выражение работает в двух местах:
- В тексте запроса набора данных — как в обычном запросе.
- В вычисляемых полях и выражениях ресурсов — на языке выражений СКД. Синтаксис тот же:
Выбор Когда … Тогда … Иначе … Конец.
Пример выражения ресурса, которое считает только просроченную задолженность:
Сумма(Выбор Когда ДнейПросрочки > 0 Тогда СуммаДолга Иначе 0 Конец)
Где что считать:
- 📌 в запросе набора — если по полю будут отбор и группировка на стороне базы данных;
- 📌 в вычисляемом поле — если формула зависит от параметров отчёта, а данных немного;
- 📌 в выражении ресурса — если условие должно применяться при подсчёте итогов на каждом уровне группировки.
Вычисляемые поля СКД считаются уже после получения данных из базы. Для отбора по большому объёму записей выносите условие в запрос — там его обработает СУБД.
Почему запрос с ВЫБОР тормозит и как ускорить
Сама конструкция дешёвая. В списке ВЫБРАТЬ она вычисляется для уже отобранных строк и почти не влияет на время. Проблемы начинаются, когда ВЫБОР попадает туда, где СУБД нужен индекс.
| Где стоит ВЫБОР | Влияние | Что сделать |
|---|---|---|
| В списке полей | минимальное | ничего |
В ГДЕ по индексированному полю | индекс не используется, сканируется вся таблица | переписать через И/ИЛИ или разбить на два запроса с ОБЪЕДИНИТЬ ВСЕ |
В условии соединения ПО | соединение без индекса | вычислить ключ заранее во временной таблице с индексом |
В СГРУППИРОВАТЬ ПО | рост объёма сортировки | сначала сгруппировать по исходным полям, ВЫБОР — во внешнем запросе |
Пример переписывания условия. Было:
ГДЕ
ВЫБОР
КОГДА &ТолькоПроведенные ТОГДА Реализация.Проведен
ИНАЧЕ ИСТИНА
КОНЕЦ
Стало:
ГДЕ
(Реализация.Проведен ИЛИ НЕ &ТолькоПроведенные)
Смысл тот же, а оптимизатору СУБД такое условие понятнее.
Ещё три приёма:
- ⚡ Временная таблица. Если одно и то же выражение нужно в нескольких запросах пакета, посчитайте его один раз в
ПОМЕСТИТЬи используйте как обычное поле. - ⚡ Без разыменования в условиях.
КОГДА Контрагент.Родитель.Родитель = …— это два неявных соединения на каждую строку. Получите нужное поле заранее. - ⚡ Частые ветки — выше. Условия проверяются по порядку. Если 90% строк попадают в одну ветку, поставьте её первой.
Ошибки при написании Выбор-Когда
Отдельно про сравнение с параметром-списком. Условие КОГДА Склад = &Склады, где в параметре массив, работать не будет. Для списка значений нужен оператор В: КОГДА Склад В (&Склады).
Чем заменить Выбор-Когда в коде и когда он не нужен
Если … ИначеЕсли во встроенном языке
Прямой аналог для кода модуля:
Если Сумма > 100000 Тогда
Группа = "Свыше 100 тыс.";
ИначеЕсли Сумма > 10000 Тогда
Группа = "10–100 тыс.";
Иначе
Группа = "До 10 тыс.";
КонецЕсли;
Тернарный оператор ?()
Для одного условия — короткая запись в одну строку:
Статус = ?(Остаток > 0, "В наличии", "Нет");
Вкладывать ?() друг в друга можно, но уже на втором уровне строка перестаёт читаться. Для трёх и более вариантов берите Если.
Соответствие вместо длинной цепочки условий
Когда результат зависит от конкретного значения (код, вид операции, статус), десяток веток удобно заменить таблицей:
Ставки = Новый Соответствие;
Ставки.Вставить("A", 0.05);
Ставки.Вставить("B", 0.10);
Ставки.Вставить("C", 0.15);
Ставка = Ставки.Получить(КодГруппы);
Если Ставка = Неопределено Тогда
Ставка = 0;
КонецЕсли;
Получить() возвращает Неопределено, если ключа нет, — это и есть ветка «иначе».
Таблица соответствий в запросе
Если в запросе ВЫБОР разросся до двадцати веток с перечислением значений, это сигнал вынести правила в данные:
- Соберите в коде таблицу значений «значение → результат».
- Передайте её параметром и поместите во временную таблицу:
ВЫБРАТЬ … ИЗ &Правила КАК Правила ПОМЕСТИТЬ ВТ_Правила. - Соедините основную таблицу с
ВТ_Правилалевым соединением по ключу.
Правила при этом меняются без правки текста запроса, а сам запрос становится короче.
Когда ВЫБОР лишний
- ❌ Подставить значение вместо
NULL— достаточноЕСТЬNULL(). - ❌ Получить текст ссылки — есть
ПРЕДСТАВЛЕНИЕ(). - ❌ Логика отбора — пишите обычное условие с
И/ИЛИ.