Разработка и Конфигурация · 12 мин
Конструкция ВЫБОР КОГДА ТОГДА в запросе 1С
Как работает конструкция ВЫБОР КОГДА ТОГДА КОНЕЦ в языке запросов 1С: синтаксис, примеры, замена NULL, типизация результата, ошибки и альтернативы.
Конструкция ВЫБОР КОГДА ТОГДА ИНАЧЕ КОНЕЦ — это аналог условного оператора в языке запросов 1С. Она позволяет прямо в тексте запроса вычислять значение поля по условиям, не прибегая к постобработке результата в коде. Это один из самых востребованных приёмов при разработке отчётов, динамических списков и обработок, где одно и то же поле должно отображаться по-разному в зависимости от данных.
Разработчики, знакомые с SQL, узнают в этой конструкции аналог CASE WHEN THEN END. Логика полностью совпадает: проверяются условия по порядку, и возвращается значение первого выполнившегося условия. Однако у реализации в 1С есть свои особенности — строгая типизация результата, взаимодействие с NULL и ограничения при использовании в виртуальных таблицах.
Ниже разобраны синтаксис, типовые сценарии применения, подводные камни с типами данных и производительностью, а также ситуации, когда условную логику лучше вынести из запроса в код или СКД.
Синтаксис конструкции ВЫБОР в запросе 1С
Базовая форма выглядит так:
ВЫБРАТЬ
ВЫБОР
КОГДА Документы.Сумма > 100000
ТОГДА "Крупная"
КОГДА Документы.Сумма > 10000
ТОГДА "Средняя"
ИНАЧЕ "Мелкая"
КОНЕЦ КАК КатегорияСделки
ИЗ
Документ.РеализацияТоваровУслуг КАК Документы
Обязательные элементы: ключевое слово ВЫБОР, хотя бы одна пара КОГДА ... ТОГДА и завершающее КОНЕЦ. Ветка ИНАЧЕ необязательна, но её отсутствие — частый источник ошибок: если ни одно условие не выполнилось и ИНАЧЕ нет, поле получит значение NULL.
Условия внутри КОГДА поддерживают сравнения, логические операторы И, ИЛИ, НЕ, проверку ЕСТЬ NULL, оператор В и даже вложенные запросы. Порядок условий важен: проверка идёт сверху вниз, и как только условие выполнилось, остальные ветки не вычисляются. Поэтому более узкие условия ставят выше более общих.
Типовые сценарии применения
Замена NULL на читаемое значение
При левых соединениях поля правой таблицы часто содержат NULL. Вместо функции ЕСТЬNULL() можно использовать ВЫБОР, когда нужна более сложная логика:
ВЫБОР
КОГДА Остатки.Количество ЕСТЬ NULL
ТОГДА 0
КОГДА Остатки.Количество < 0
ТОГДА 0
ИНАЧЕ Остатки.Количество
КОНЕЦ КАК ДоступныйОстаток
Для простой замены NULL одним значением предпочтительнее ЕСТЬNULL(Поле, Значение) — она короче и читается легче. ВЫБОР оправдан, когда ветвлений два и больше.
Вычисляемые признаки и статусы
Частый сценарий — вывести текстовый статус документа на основе нескольких полей: проведён ли, оплачен ли, отгружен ли. Вместо трёх отдельных колонок в отчёте формируется одна сводная:
ВЫБОР
КОГДА НЕ Заказ.Проведен
ТОГДА "Черновик"
КОГДА Оплата.СуммаОплаты >= Заказ.СуммаДокумента
ТОГДА "Оплачен"
ИНАЧЕ "Ожидает оплаты"
КОНЕЦ КАК Статус
Выбор источника данных
Конструкция позволяет брать значение из разных полей в зависимости от условия — например, цену из договора, а если она не задана, то из карточки номенклатуры. Это избавляет от соединения с дополнительными таблицами ради одного поля.
- 1Определите, какое поле или комбинация полей определяет логику ветвления
- 2Запишите условия от частного к общему, самое узкое — первым
- 3Убедитесь, что все ветки ТОГДА возвращают один и тот же тип данных
- 4Добавьте ветку ИНАЧЕ со значением по умолчанию
- 5Выполните запрос в консоли запросов и проверьте результат на граничных значениях: NULL, ноль, пустая строка
Типизация результата: главное ограничение
Все ветки ТОГДА и ИНАЧЕ должны возвращать значения совместимых типов. Если одна ветка возвращает строку, а другая — число, платформа либо выдаст ошибку при выполнении запроса, либо приведёт значения к общему типу с неожиданным результатом, особенно в СКД.
Особое внимание — к строкам разной длины. Если в одной ветке литерал "Оплачен", а в другой переменная строкового типа неограниченной длины, в динамических списках и СКД могут возникнуть проблемы с сортировкой и отбором. Практическое правило: приводить строки к явной длине через ВЫРАЗИТЬ(... КАК СТРОКА(50)).
Со ссылочными типами ситуация сложнее. Если ветки возвращают ссылки на разные справочники, поле получит составной тип, что усложнит дальнейшую работу с результатом — отборы, группировки и обращение к реквизитам через точку станут невозможны или потребуют дополнительного ВЫРАЗИТЬ.
ВЫБОР и NULL: взаимодействие и ловушки
Ключевой нюанс: сравнение Поле = NULL в запросе никогда не истинно. Условие КОГДА Остатки.Количество = NULL не сработает ни при каких данных. Для проверки на NULL используется только ЕСТЬ NULL:
ВЫБОР
КОГДА Остатки.Количество ЕСТЬ NULL
ТОГДА "Нет на складе"
ИНАЧЕ "В наличии"
КОНЕЦ КАК НаличиеТовара
Вторая ловушка — NULL в арифметике. Если поле, участвующее в вычислении внутри ТОГДА, содержит NULL, результатом будет NULL, даже если само условие КОГДА выполнилось. Поэтому поля из левых соединений перед вычислениями оборачивают в ЕСТЬNULL.
Третий момент: если ни одно условие не выполнилось и ветки ИНАЧЕ нет, результат — NULL. В СКД такое поле может отображаться пустым, а при группировке NULL образует отдельную группу, что искажает итоги. Всегда задавайте ИНАЧЕ, если логика не предполагает осознанного использования NULL.
Производительность и ограничения
Сама по себе конструкция ВЫБОР вычисляется быстро — это построчная операция над уже выбранными данными. Проблемы начинаются, когда ВЫБОР используется в предложении ГДЕ или в условиях соединения: в этом случае СУБД часто не может применить индекс, и запрос превращается в полное сканирование таблицы.
Правило простое: ВЫБОР в списке выбираемых полей — почти всегда безопасно; ВЫБОР в отборе — повод переписать запрос. Условие вида ГДЕ ВЫБОР КОГДА ... КОНЕЦ = &Значение обычно заменяют на эквивалентную комбинацию простых условий через И/ИЛИ, которые оптимизатор обрабатывает эффективно.
Вложенные запросы внутри КОГДА допустимы синтаксически, но резко ухудшают читаемость и могут выполняться многократно. Если логика требует обращения к другим таблицам, соедините их в основном запросе и используйте ВЫБОР только для выбора между уже полученными полями.
Если отчёт строится на СКД, простые ветвления оформления (цвет строки, формат) лучше делать средствами условного оформления СКД, а не ВЫБОРом в запросе. ВЫБОР оставляйте для данных, которые реально участвуют в группировках, отборах или выгружаются для дальнейшей обработки.
Альтернативы: ЕСТЬNULL, СКД, постобработка
ВЫБОР — не единственный способ реализовать условную логику. Для замены NULL достаточно функции ЕСТЬNULL. Для представления данных в отчёте подходят вычисляемые поля СКД и условное оформление. Для сложной бизнес-логики, зависящей от множества факторов, иногда честнее выбрать сырые данные запросом и обработать их в коде на встроенном языке.
Чем заменить ВЫБОР
Только замена NULL одним значением. Короче и читабельнее, но не поддерживает ветвления
Подходит для отчётов на СКД, когда логика нужна только для отображения. Не работает в обычных запросах и динамических списках
Для сложной логики с обращением к функциям и менеджерам объектов. Медленнее на больших выборках, гибче по возможностям
Визуальное выделение по условию без изменения данных. Не подходит, если значение нужно для отбора или группировки
Критерий выбора: если результат нужен в отборе, группировке или соединении — логика должна быть в запросе, то есть ВЫБОР. Если результат нужен только для показа пользователю — рассмотрите вычисляемые поля и оформление СКД. Если логика требует функционала, недоступного в языке запросов (обращение к методам объектов, сложные строковые преобразования) — постобработка в коде.
Как выбрать подход
Проверка результата и отладка
Перед переносом запроса в конфигурацию проверяйте его в консоли запросов на данных, включающих граничные случаи: записи с NULL в ключевых полях, нулевые и отрицательные числа, пустые строки и даты. Именно на таких значениях конструкция ВЫБОР ведёт себя неочевидно.
Полезный приём — временно вывести в запрос исходные поля, участвующие в условиях, рядом с вычисляемым полем. Так сразу видно, почему конкретная строка попала в ту или иную ветку. После отладки лишние поля убирают.
Если запрос используется в СКД, дополнительно проверьте тип поля на закладке «Наборы данных»: платформа определяет тип вычисляемого выражения автоматически, и при составных типах в ветках там может оказаться не то, что ожидалось. Явно задайте тип поля, если автоматическое определение некорректно.
Как проверить результат
Поле заполнено значением из ветки ИНАЧЕ или обработки NULL
Пустые значения там, где их быть не должно
Один однозначный тип, соответствующий логике
Составной тип или неожиданное приведение
Группы соответствуют задуманным категориям
Отдельная группа с пустым значением
Сопоставимо с запросом без ВЫБОР
Резкий рост времени — ВЫБОР попал в отбор или соединение
Часто задаваемые вопросы
Чем ВЫБОР отличается от ЕСТЬNULL?
ЕСТЬNULL решает одну задачу — замену NULL заданным значением. ВЫБОР поддерживает произвольное число условий и разные возвращаемые значения. Если нужна только замена NULL, ЕСТЬNULL короче и читаемее; для ветвлений — только ВЫБОР.
Можно ли использовать ВЫБОР в условии ГДЕ?
Синтаксически да, но это почти всегда плохое решение: СУБД не сможет использовать индексы, и запрос замедлится. Перепишите условие через эквивалентную комбинацию простых сравнений с операторами И и ИЛИ.
Почему условие КОГДА Поле = NULL не работает?
В языке запросов любое сравнение с NULL даёт неопределённый результат, а не Истину. Проверка на NULL выполняется только конструкцией «Поле ЕСТЬ NULL», а отрицание — «НЕ Поле ЕСТЬ NULL».
Что вернёт ВЫБОР, если ни одно условие не выполнилось?
Если ветка ИНАЧЕ задана — её значение. Если ИНАЧЕ отсутствует — NULL. В отчётах такие NULL образуют отдельную группу при группировке и могут искажать итоги, поэтому ИНАЧЕ рекомендуется указывать всегда.
Можно ли вкладывать один ВЫБОР внутрь другого?
Да, вложенные конструкции допустимы и работают корректно. Однако глубокая вложенность резко снижает читаемость запроса. При более чем двух уровнях стоит пересмотреть логику: возможно, часть условий лучше объединить или вынести в отдельное вычисляемое поле.
Работает ли ВЫБОР в параметрах виртуальных таблиц?
Нет, в параметрах виртуальных таблиц (условия отбора регистров) конструкция ВЫБОР не поддерживается. Условия там задаются простыми сравнениями полей с параметрами. Сначала отберите данные виртуальной таблицей, а ВЫБОР применяйте уже к результату соединения.
Что важно запомнить
ВЫБОР КОГДА ТОГДА ИНАЧЕ КОНЕЦ — условная конструкция запроса 1С для вычисления поля по цепочке условий. Все ветки должны возвращать совместимые типы, проверка NULL — только через ЕСТЬ NULL, ветка ИНАЧЕ — практически обязательна. В списке полей ВЫБОР безопасен, в отборах — вреден для производительности. Для простой замены NULL используйте ЕСТЬNULL, для оформления отчётов — возможности СКД.