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

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

Выбор когда несколько условий в 1С: запросы, код и типичные ошибки

Как правильно использовать конструкцию ВЫБОР КОГДА с несколькими условиями в запросах 1С и оператор Если в коде. Примеры, ошибки, проверка результата.

Задача «выбрать значение по нескольким условиям» встречается в 1С постоянно: подставить ставку НДС в зависимости от товара и даты, рассчитать скидку по сумме и категории клиента, вывести статус документа в отчёте. Для этого есть два основных инструмента — конструкция ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ в языке запросов и оператор Если ... Тогда ... ИначеЕсли ... КонецЕсли во встроенном языке. У них разный синтаксис, разные ограничения и разные типичные ошибки.

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

Вторая частая проблема — отсутствие ветки ИНАЧЕ. Если ни одно условие не сработало и ИНАЧЕ не задано, результат будет NULL, что сломает сравнения, группировки и итоги в отчёте. Ниже разберём синтаксис, сценарии с несколькими условиями, соединениями И/ИЛИ, проверку результата и типичные ошибки.

Синтаксис ВЫБОР КОГДА в языке запросов

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

ВЫБРАТЬ

ВЫБОР

КОГДА Продажи.Сумма >= 100000

ТОГДА "Крупная"

КОГДА Продажи.Сумма >= 10000

ТОГДА "Средняя"

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

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

ИЗ

РегистрНакопления.Продажи КАК Продажи

Обратите внимание на порядок: сначала проверяется порог 100 000, затем 10 000. Если поменять их местами, все суммы от 10 000 попадут в «Средняя», а категория «Крупная» останется пустой. Платформа не сообщит об ошибке — данные будут просто неправильными.

Результат каждой ветки ТОГДА должен иметь совместимый тип. Смешивать строку, число и дату в разных ветках нельзя — запрос завершится с ошибкой. Если нужен составной тип, приводите значения к одному типу через ВЫРАЗИТЬ.

Несколько условий через И и ИЛИ

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

ВЫБОР

КОГДА Заказ.Сумма > 50000

И Заказ.Контрагент.Категория = "VIP"

ТОГДА Заказ.Сумма * 0.15

КОГДА Заказ.Сумма > 50000

ИЛИ Заказ.Контрагент.Категория = "VIP"

ТОГДА Заказ.Сумма * 0.10

ИНАЧЕ 0

КОНЕЦ КАК Скидка

Здесь важны две вещи. Во-первых, приоритет: И выполняется раньше ИЛИ, поэтому при сложных комбинациях ставьте скобки явно — это уберегает от неочевидной логики. Во-вторых, порядок веток: условие с И (более строгое) стоит выше условия с ИЛИ (более мягкого), иначе строгое никогда не сработает.

Для проверки вхождения в список значений вместо цепочки ИЛИ используйте оператор В: КОГДА Товар.Вид В (&СписокВидов). Это короче, читаемее и обычно быстрее выполняется.

ВЫБОР КОГДА с соединениями и NULL

При левом соединении таблиц поля присоединённой таблицы могут быть NULL. Сравнение NULL = 0 возвращает не Истина и не Ложь, а неопределённость, поэтому условие не сработает. Частая ошибка — проверять поле из левого соединения напрямую.

Правильный подход — функция ЕСТЬNULL или явная проверка ЕСТЬ NULL:

ВЫБОР

КОГДА Остатки.Количество ЕСТЬ NULL

ТОГДА "Нет на складе"

КОГДА Остатки.Количество <= Товары.МинимальныйЗапас

ТОГДА "Заказать"

ИНАЧЕ "Достаточно"

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

Либо заранее подменить значение: ЕСТЬNULL(Остатки.Количество, 0) <= Товары.МинимальныйЗапас. Оба варианта рабочие; ЕСТЬNULL удобнее, когда значение нужно ещё и выводить, а проверка ЕСТЬ NULL — когда «отсутствие записи» и «нулевое значение» смыслово различаются.

Несколько условий во встроенном языке: Если и ?()

Во встроенном языке (модули, обработчики) используется оператор Если:

Если Сумма >= 100000 И КлиентVIP Тогда

Скидка = 15;

ИначеЕсли Сумма >= 100000 Или КлиентVIP Тогда

Скидка = 10;

Иначе

Скидка = 0;

КонецЕсли;

Для простого выбора из двух значений удобен тернарный оператор: Ставка = ?(Налогообложение = "ОСНО", 20, 0);. Но вкладывать несколько ?() друг в друга не стоит — такой код тяжело читать и отлаживать, при трёх и более вариантах переходите на Если ... ИначеЕсли.

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

Выбор из нескольких значений перечисления или справочника

Когда условие — это сравнение одного поля с разными фиксированными значениями, цепочка КОГДА работает, но быстро разрастается. Для 3–5 вариантов это нормально:

ВЫБОР

КОГДА Док.Статус = ЗНАЧЕНИЕ(Перечисление.Статусы.Черновик)

ТОГДА 1

КОГДА Док.Статус = ЗНАЧЕНИЕ(Перечисление.Статусы.Согласован)

ТОГДА 2

ИНАЧЕ 3

КОНЕЦ КАК ПорядокСортировки

Если вариантов больше десятка или соответствие часто меняется, лучше вынести его в данные: дополнительный реквизит справочника, регистр сведений «Соответствие статусов и порядка» и соединение с ним в запросе. Тогда изменение настройки не потребует правки кода и обновления конфигурации.

Способы задать соответствие

Цепочка КОГДА в запросе

Подходит для 2–5 фиксированных вариантов. Меняется только правкой запроса, требует обновления конфигурации или внешней обработки.

Регистр сведений с соответствием

Подходит для десятков вариантов и часто меняющихся настроек. Пользователь редактирует данные сам, запрос остаётся неизменным. Чуть сложнее в реализации.

Реквизит справочника

Подходит, когда значение — свойство самого объекта (например, порядок сортировки у вида номенклатуры). Просто и наглядно, но только для соответствий «один объект — одно значение».

Проверка результата и типичные ошибки

После написания условий обязательно проверьте результат на граничных значениях: ровно на пороге (100 000), чуть ниже и выше, пустое значение, NULL, нулевое количество. Удобный способ — временно вывести в запросе сами проверяемые поля рядом с вычисленным результатом и глазами сверить несколько десятков строк.

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

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

Граничные значения
Норма

Значение ровно на пороге попадает в ожидаемую ветку

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

Пороговое значение попадает не туда или нигде не выводится

Пустые и NULL-поля
Норма

Строки с пустыми полями получают значение из ИНАЧЕ

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

Часть строк имеет пустой результат или отсутствует в выборке

Полнота данных
Норма

Количество строк результата совпадает с запросом без ВЫБОР КОГДА

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

Строк стало меньше — условие где-то отсекает данные

Типы значений
Норма

Все ветки ТОГДА возвращают один тип

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

Запрос падает с ошибкой несовместимости типов

Типичные ошибки
01
Общее условие выше частного — частная ветка никогда не срабатывает, ошибки нет, данные неверные.
02
Нет ветки ИНАЧЕ — несработавшие строки получают NULL, ломаются итоги и сравнения.
03
Сравнение поля из левого соединения без ЕСТЬNULL — условие молча не срабатывает для отсутствующих записей.
04
Смешение типов в ветках ТОГДА — запрос падает с ошибкой несовместимости типов.
05
Условия И/ИЛИ без скобок при смешанной логике — фактический порядок проверки отличается от задуманного.
06
Сравнение перечисления со строкой вместо ЗНАЧЕНИЕ(...) — условие всегда ложно.

Производительность и ограничения

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

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

Маршрут решения

Как выбрать подход

Нужно выбрать значение в запросе по 2–5 условиямИспользуйте ВЫБОР КОГДА с веткой ИНАЧЕ, частные условия выше общих
Логика нужна в коде модуля, а не в запросеИспользуйте Если...ИначеЕсли...Иначе, для двух вариантов — тернарный оператор ?()
Условие проверяет поле из левого соединенияОберните поле в ЕСТЬNULL или добавьте отдельную ветку с проверкой ЕСТЬ NULL
Вариантов больше десятка или они меняются пользователямиВынесите соответствие в регистр сведений и замените ВЫБОР на соединение
Условие используется в отборе и запрос тормозитПерепишите на ОБЪЕДИНИТЬ ВСЕ с простыми условиями в каждой части

FAQ

Что вернёт ВЫБОР КОГДА, если ни одно условие не сработало и ИНАЧЕ нет?

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

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

Да, вложенность допускается и иногда оправдана — например, сначала проверить вид документа, а внутри уже условия по сумме. Но при глубине больше двух уровней запрос становится трудно читать; обычно лучше разбить логику на несколько вычисляемых полей или вынести соответствия в данные.

Почему условие по перечислению не срабатывает?

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

Чем отличается И от ИЛИ по приоритету и нужны ли скобки?

Оператор И имеет более высокий приоритет и выполняется раньше ИЛИ. Выражение «А И Б ИЛИ В» читается как «(А И Б) ИЛИ В». Если задумано «А И (Б ИЛИ В)» — скобки обязательны. Рекомендуется ставить скобки всегда при смешивании И и ИЛИ, чтобы логика была очевидна при чтении.

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

Для ссылочных типов — сравнение с пустой ссылкой через ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка) или значение НЕОПРЕДЕЛЕНО в зависимости от типа. Для строк — сравнение с "" или проверка длины. Для полей из левого соединения дополнительно учитывайте NULL через ЕСТЬNULL или ЕСТЬ NULL.

Есть ли аналог ВЫБОР КОГДА в СКД?

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

Итог

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

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