К статье
Практический материал

Разработка и Конфигурация · 11 мин

Условие ВЫБОР КОГДА в запросе 1С 8.3: синтаксис, примеры и ошибки

Как использовать условие ВЫБОР КОГДА ТОГДА ИНАЧЕ КОНЕЦ в запросе 1С 8.3: синтаксис, примеры, типовые ошибки, сравнение с ГДЕ и советы по производительности.

Условная логика внутри запроса — одна из самых востребованных возможностей языка запросов 1С 8.3. Конструкция ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ позволяет вычислять значение поля прямо на уровне СУБД, не выгружая данные в код и не перебирая их в цикле. Это аналог оператора CASE в SQL.

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

Ниже разобраны синтаксис, практические примеры на реальных задачах (статусы документов, расчёт скидок, группировка по условию), ограничения по типам данных, влияние на скорость выполнения и типичные ошибки, из-за которых запрос либо падает, либо возвращает неожиданный результат.

Синтаксис конструкции ВЫБОР КОГДА

Полная форма условного выражения выглядит так:

ВЫБОР

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

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

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

КОНЕЦ

Условия проверяются последовательно сверху вниз. Как только одно из них оказалось истинным, возвращается соответствующее значение, а остальные ветки не вычисляются. Поэтому порядок условий имеет значение: более частные проверки ставьте выше общих.

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

Существует и сокращённая форма для булевых полей: ВЫБОР КОГДА Проведен ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ КОНЕЦ — но проще написать само булево выражение, если оно уже возвращает нужный тип.

Чем КОГДА отличается от ГДЕ

Путаница между этими конструкциями — самая частая проблема у начинающих. Различие принципиально: ГДЕ фильтрует строки результата, а ВЫБОР КОГДА формирует значение поля внутри каждой строки. ГДЕ отвечает на вопрос «какие записи показать», КОГДА — «что вывести в колонке».

Пример с ГДЕ — выбираем только проведённые документы:

ВЫБРАТЬ

Реализация.Ссылка,

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

ИЗ

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

ГДЕ

Реализация.Проведен

Пример с ВЫБОР КОГДА — выбираем все документы, но помечаем их статусом:

ВЫБРАТЬ

Реализация.Ссылка,

ВЫБОР

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

КОГДА Реализация.ПометкаУдаления ТОГДА "Удалён"

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

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

ИЗ

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

Сравнение вариантов

ГДЕ (отбор строк)

Подходит, когда нужно исключить часть записей из результата. Ограничение: отфильтрованные строки недоступны для группировки и итогов.

ВЫБОР КОГДА (вычисляемое поле)

Подходит, когда все строки нужны, но значение колонки зависит от условия. Ограничение: не уменьшает объём выборки.

ВЫБОР КОГДА внутри агрегата

Например, СУММА(ВЫБОР КОГДА ... ТОГДА Сумма ИНАЧЕ 0 КОНЕЦ) — подходит для сводных итогов по нескольким категориям в одном запросе.

Практические примеры использования

Классификация по диапазонам значений

Типовая задача — разбить контрагентов на категории по сумме продаж:

ВЫБРАТЬ

Продажи.Контрагент,

Продажи.СуммаОборот,

ВЫБОР

КОГДА Продажи.СуммаОборот >= 1000000 ТОГДА "Крупный"

КОГДА Продажи.СуммаОборот >= 100000 ТОГДА "Средний"

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

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

ИЗ

РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , ) КАК Продажи

Обратите внимание: условия проверяются сверху вниз, поэтому проверка на миллион стоит первой. Если поменять ветки местами, крупные клиенты попадут в «Средний», потому что условие >= 100000 сработает раньше.

Вычисление суммы с условием

Классический приём для сводных отчётов — агрегат вокруг ВЫБОРА. Например, отдельно посчитать отгруженную и оплаченную суммы в одной выборке:

ВЫБРАТЬ

Расчёты.Контрагент,

СУММА(ВЫБОР

КОГДА Расчёты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)

ТОГДА Расчёты.Сумма

ИНАЧЕ 0

КОНЕЦ) КАК Отгружено,

СУММА(ВЫБОР

КОГДА Расчёты.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)

ТОГДА Расчёты.Сумма

ИНАЧЕ 0

КОНЕЦ) КАК Оплачено

ИЗ

РегистрНакопления.РасчётыСКонтрагентами КАК Расчёты

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

Расчёты.Контрагент

Подстановка значения при NULL

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

Порядок действий при добавлении условия в запрос
  1. 1
    Определите, что нужно: отфильтровать строки (ГДЕ) или вычислить значение поля (ВЫБОР КОГДА)
  2. 2
    Напишите условия от частного к общему, проверяя типы значений в каждой ветке
  3. 3
    Добавьте ветку ИНАЧЕ с безопасным значением по умолчанию
  4. 4
    Выполните запрос в консоли запросов на копии базы и проверьте результат на граничных данных
  5. 5
    Проверьте, что в поле не появляются неожиданные NULL и что типы колонок соответствуют ожиданиям

Ограничения и типы данных

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

Строковые литералы в разных ветках приводятся к максимальной длине, но при последующем сравнении такого поля с параметром фиксированной длины возможны сюрпризы. Если результат ВЫБОРА участвует в соединениях или отборах, лучше явно привести тип через ВЫРАЗИТЬ(... КАК Строка(50)).

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

Влияние на производительность

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

Если нужно отфильтровать по результату условия, не оборачивайте ВЫБОР в ГДЕ запроса верхнего уровня без необходимости. Часто эффективнее расписать условие дизьюнкцией: вместо ГДЕ ВЫБОР КОГДА Т.Тип = 1 ТОГДА Т.Сумма ИНАЧЕ 0 КОНЕЦ > 100 написать ГДЕ (Т.Тип = 1 И Т.Сумма > 100) ИЛИ (Т.Тип <> 1 И 0 > 100) — оптимизатор справится с таким вариантом лучше.

Для виртуальных таблиц регистров помните: параметры виртуальной таблицы (период, условие) обрабатываются до основного запроса и существенно сокращают выборку. Условие, которое можно передать в параметры виртуальной таблицы, всегда лучше разместить там, а не в ГДЕ основного запроса.

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

Первая ошибка — отсутствие ИНАЧЕ. Разработчик перечисляет все известные значения перечисления, но со временем в конфигурацию добавляют новое, и запрос молча начинает возвращать NULL. Ветка ИНАЧЕ с явным значением по умолчанию страхует от этого.

Вторая ошибка — несовпадение типов в ветках. Например, в одной ветке ссылка на справочник, в другой — пустая строка. Запрос выполнится, но при обходе результата код, ожидающий ссылку, упадёт или отработает неверно. Для «пустого» значения ссылочного типа используйте ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка).

Третья ошибка — сравнение с NULL через равенство, описанная выше. Четвёртая — неправильный порядок условий при диапазонах: сначала проверяется широкое условие, и узкие ветки становятся недостижимыми. Пятая — попытка использовать ВЫБОР там, где нужна фильтрация ГДЕ: запрос выбирает лишние миллионы строк, а потом код их отбрасывает.

Типичные ошибки
01
Пропущена ветка ИНАЧЕ — при новых значениях данных поле молча возвращает NULL
02
Сравнение с NULL через равенство — условие никогда не выполняется, используйте ЕСТЬ NULL
03
Разные типы в ветках ТОГДА и ИНАЧЕ — составной тип колонки ломает дальнейшую обработку
04
Неверный порядок условий при диапазонах — узкие условия никогда не срабатывают
05
ВЫБОР вместо ГДЕ для отбора — выбираются лишние строки и растёт время выполнения

Проверка результата и отладка

Отлаживать условные выражения удобнее всего в консоли запросов: временно выведите рядом с вычисляемым полем исходные поля, участвующие в условии. Так сразу видно, почему конкретная строка попала в ту или иную ветку.

Полезный приём — проверка граничных значений: нулевая сумма, пустая ссылка, NULL от левого соединения, даты на границе периода. Именно на таких данных условная логика ломается чаще всего. Если запрос использует соединения, отдельно проверьте строки, где правая таблица не нашла совпадений.

Для сложных многоуровневых условий разбейте запрос: поместите промежуточный результат с вычисленным полем во временную таблицу, а дальнейшие отборы и группировки выполняйте уже над ней. Это упрощает и отладку, и повторное использование вычисленного значения.

Контрольные точки

Как проверить результат

Значения вычисляемого поля
Норма

Каждая строка попала в ожидаемую ветку, NULL отсутствуют или объяснимы

Тревожный признак

Появляются NULL там, где должно быть значение по умолчанию

Тип колонки результата
Норма

Один тип во всех строках, совместимый с дальнейшей обработкой

Тревожный признак

Смешанные типы (строки и числа, ссылки разных видов)

Время выполнения
Норма

Запрос отрабатывает за приемлемое время на реальном объёме данных

Тревожный признак

Резкое замедление после добавления условия в соединение или группировку

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

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

Да, синтаксис это допускает, но делать так стоит редко: отбор по вычисляемому выражению обычно не использует индексы. В большинстве случаев условие можно переписать через И и ИЛИ так, чтобы сравнения шли напрямую по полям таблицы.

Чем ВЫБОР КОГДА отличается от функции ЕСТЬNULL?

ЕСТЬNULL(Поле, Значение) — частный случай: заменить NULL конкретным значением. ВЫБОР КОГДА универсальнее и поддерживает любые условия и любое количество веток. Для простой подстановки вместо NULL используйте ЕСТЬNULL — запись короче и понятнее.

Сколько веток КОГДА можно написать в одном ВЫБОРЕ?

Жёсткого практического лимита, с которым сталкиваются на реальных задачах, нет. Однако конструкции с десятками веток тяжело читать и отлаживать. Если веток много и они описывают соответствие «ключ — значение», лучше создать таблицу соответствий (например, в параметре-таблице значений) и соединиться с ней.

Можно ли вкладывать один ВЫБОР внутрь другого?

Можно, вложенность поддерживается и в условиях, и в значениях веток. Но уже два-три уровня делают текст нечитаемым. В таких случаях переносите часть логики во временную таблицу с промежуточным вычисленным полем.

Почему ВЫБОР возвращает NULL, хотя все значения перечислены?

Значит, в данных встретилось значение, не попавшее ни в одно условие: новый элемент перечисления, NULL от соединения или значение другого типа. Добавьте ветку ИНАЧЕ и выведите исходное поле рядом с вычисляемым — сразу увидите проблемные строки.

Работает ли ВЫБОР КОГДА в СКД и динамических списках?

Да, конструкция полностью поддерживается в тексте запроса для СКД и в произвольном запросе динамического списка. Для динамических списков учитывайте ограничение: если нужна интерактивная сортировка по вычисляемому полю, оно должно быть доступно в наборе данных списка.

Итог

Что важно запомнить

ВЫБОР КОГДА вычисляет значение поля, ГДЕ отбирает строки — это разные задачи. Условия перечисляйте от частного к общему, ветку ИНАЧЕ указывайте всегда, типы во всех ветках держите совместимыми, а NULL проверяйте только через ЕСТЬ NULL. Сложные условия отлаживайте в консоли запросов на копии базы.