Оператор Когда-Тогда является одним из фундаментальных инструментов в языке запросов платформы 1С:Предприятие. Эта конструкция позволяет осуществлять условную фильтрацию данных, аналогичную оператору CASE в стандартном SQL, но с расширенными возможностями, специфичными для архитектуры 1С. Понимание принципов работы этого оператора критически важно для разработчиков, создающих сложные отчеты и обработки.

В отличие от простых условий в блоке ГДЕ, конструкция Когда-Тогда позволяет формировать результирующий набор данных, где значения полей могут динамически меняться в зависимости от заданных условий. Это особенно актуально при работе с накопительными регистрами и виртуальными таблицами, где логика выборки часто требует гибкости.

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

Синтаксис и базовое применение конструкции

Базовый синтаксис оператора строится по принципу проверки условий последовательно. Если первое условие истинно, выполняется соответствующее действие, и проверка прекращается. Если нет — система переходит к следующему условию. Это поведение напоминает каскад if-else в процедурном коде.

Рассмотрим простейший пример использования оператора для классификации товаров по группам в зависимости от их номенклатурной группы. Здесь мы используем ключевое слово ВЫРАЗИТЬ для явного приведения типа результата.

ВЫБРАТЬ

Номенклатура.Ссылка,

ВЫБОР

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

ТОГДА "Товар"

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

ТОГДА "Услуга"

ИНАЧЕ "Прочее"

КОНЕЦ КАК ТипОбъекта

ИЗ

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

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

⚠️ Внимание: Количество условий в конструкции Когда-Тогда не ограничено жестко, но чрезмерное усложнение логики внутри одного запроса может затруднить чтение кода и усложнить отладку. Старайтесь выносить сложную бизнес-логику в отдельные временные таблицы, если условий становится больше пяти.

💡

Используйте форматирование с отступами для каждого уровня вложенности внутри ВЫБОР..КОНЕЦ. Это значительно упрощает визуальный анализ структуры запроса при чтении коллегами.

Работа с виртуальными таблицами и срезами

Особую мощ конструкция Когда-Тогда раскрывает при работе с виртуальными таблицами регистров. В 1С часто возникает задача получить срез данных на разные даты для разных объектов в рамках одного запроса. Стандартный параметр (, &Период) здесь не подходит, так как период един для всей выборки.

Именно в таких случаях применяется динамическое указание периода. Вы можете передавать в виртуальную таблицу значение поля из другой таблицы или результат вычисления. Это позволяет строить отчеты типа "Остатки на дату последнего движения" без использования временных таблиц.

ВЫБРАТЬ

ОстаткиТоваров.Номенклатура,

ОстаткиТоваров.КоличествоОстаток

ИЗ

РегистрНакопления.ТоварыНаСкладах.Остатки(

,

ВЫБОР

КОГДА &РежимОтчета = "НаКонецМесяца"

ТОГДА &ДатаКонецМесяца

КОГДА &РежимОтчета = "НаДатуДокумента"

ТОГДА Документы.Дата

ИНАЧЕ &ТекущаяДата

КОНЕЦ

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

Такой подход существенно экономит ресурсы сервера, так как выборка происходит одним обращением к СУБД. Однако следует помнить, что использование полей из других таблиц в параметрах виртуальных таблиц может влиять на возможность использования индексов.

📊 С каким типом регистров вы чаще всего используете конструкцию Когда-Тогда?
Регистры накопления
Регистры сведений
Регистры бухгалтерии
Регистры расчета

Вложенные конструкции и приоритет вычислений

Язык запросов 1С допускает вложенность операторов ВЫБОР. Это необходимо, когда логика выбора зависит от нескольких независимых факторов. Например, сначала мы проверяем статус документа, а затем, если он проведен, проверяем сумму.

При написании вложенных конструкций важно соблюдать правильный порядок закрытия блоков КОНЕЦ. Ошибка в количестве закрывающих ключевых слов является одной из самых частых причин синтаксических ошибок при компиляции запроса.

Рассмотрим пример, где вложенность используется для расчета коэффициента скидки в зависимости от типа клиента и объема закупки:

ВЫБОР

КОГДА Контрагент.ЭтоГруппа

ТОГДА 0

ИНАЧЕ

ВЫБОР

КОГДА СуммаДокумента > 100000

ТОГДА 0.1

КОГДА СуммаДокумента > 50000

ТОГДА 0.05

ИНАЧЕ 0

КОНЕЦ

КОНЕЦ КАК КоэффициентСкидки

В данном примере внешняя проверка отсеивает групповые элементы справочника, для которых скидка не применяется. Внутренняя проверка анализирует числовые значения. Такая структура делает код модульным и понятным.

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

Оптимизация вложенных выборов

СУБД может неэффективно выполнять план запроса при сложных вложенных условиях. Иногда выгоднее сделать два простых запроса и объединить их оператором ОБЪЕДИНИТЬ ВСЕ, чем писать одну монструозную конструкцию ВЫБОР.

Использование с агрегатными функциями

Конструкция Когда-Тогда часто применяется внутри агрегатных функций, таких как СУММА, МИНИМУМ, МАКСИМУМ или СРЕДНЕЕ. Это позволяет выполнять условное агрегирование данных, известное также как "сводные таблицы в SQL".

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

Функция Описание использования Пример условия
СУММА Суммирование только тех строк, где условие истинно СУММА(ВЫБОР КОГДА.. ТОГДА Сумма ИНАЧЕ 0 КОНЕЦ)
МИНИМУМ Поиск минимального значения среди отфильтрованных МИНИМУМ(ВЫБОР КОГДА.. ТОГДА Цена ИНАЧЕ NULL КОНЕЦ)
КОЛИЧЕСТВО Подсчет количества записей, удовлетворяющих условию СУММА(ВЫБОР КОГДА.. ТОГДА 1 ИНАЧЕ 0 КОНЕЦ)

Однако для функций МИНИМУМ и МАКСИМУМ использование NULL в ветке ИНАЧЕ предпочтительнее, так как агрегатные функции игнорируют пустые значения.

💡

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

Обработка NULL значений и типы данных

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

Особое внимание следует уделить обработке NULL. В языке запросов 1С NULL означает неопределенное значение. Сравнение любого значения с NULL через оператор равно (=) всегда дает ЛОЖЬ. Для проверки на пустое значение необходимо использовать конструкцию ЕСТЬ NULL.

ВЫБОР

КОГДА ПолеСДатою ЕСТЬ NULL

ТОГДА ДАТАВРЕМЯ(1900, 1, 1)

ИНАЧЕ ПолеСДатою

КОНЕЦ КАК РабочаяДата

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

⚠️ Внимание: Тип возвращаемого значения всей конструкции ВЫБОР определяется как наиболее общий тип для всех веток. Если в одной ветке возвращается Число, а в другой Строка, результат будет типом Универсальный, что ухудшает производительность и может вызвать ошибки при сохранении во временную таблицу с жесткой структурой.

☑️ Проверка типов в конструкции ВЫБОР

Выполнено: 0 / 4

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

Использование конструкции Когда-Тогда напрямую влияет на план выполнения запроса оптимизатором СУБД. В большинстве случаев современные серверы баз данных (MS SQL, PostgreSQL) эффективно обрабатывают такие условия, превращая их в план выполнения без значительных накладных расходов.

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

Для оптимизации рекомендуется:

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

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

Можно ли использовать конструкцию Когда-Тогда в предложении ГДЕ?

Да, можно. Конструкция ВЫБОР..КОНЕЦ возвращает значение, которое может участвовать в сравнении. Например: ГДЕ ВЫБОР КОГДА.. ТОГДА 1 ИНАЧЕ 0 КОНЕЦ = 1. Однако чаще эффективнее расписать условия через И и ИЛИ для лучшего использования индексов.

Что делать, если типы данных в ветках ТОГДА не совпадают?

Необходимо явно привести их к общему типу с помощью функции ВЫРАЗИТЬ(.. КАК..). Например, если одна ветка возвращает число, а другая строку, приведите число к строке или наоборот, в зависимости от логики задачи.

Есть ли ограничение на количество условий КОГДА?

Технического ограничения в языке запросов 1С нет, но есть практические лимиты сложности запроса, накладываемые СУБД. При превышении разумных пределов (сотни условий) запрос может не скомпилироваться или выполняться крайне медленно.

Как работает конструкция, если ни одно условие не выполнилось и нет ИНАЧЕ?

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