Как разобраться в конструкции ВЫБОР КОГДА ВЫБОР КОГДА в запросах 1С

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При работе с типовыми конфигурациями (например, ЗУП 3.1 или ERP 2.5) разработчики часто сталкиваются с громоздкими конструкциями в языке запросов. Одной из самых «зубодробительных» является вложенный оператор ВЫБОР, результат которого сразу используется как условие для другого ВЫБОР. Рассмотрим подробно, как читать такой код, как он работает с точки зрения логики и как его упростить для понимания.

Разбор исходной ситуации

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


ВЫБОР 
    КОГДА ВЫБОР 
            КОГДА НЕ ТаблицаДанных.ОтборПоВидуЕжегодногоОтпуска = ЗНАЧЕНИЕ(Справочник.ВидыЕжегодныхОтпусков.ПустаяСсылка) 
                ТОГДА ТаблицаДанных.ОтборПоВидуЕжегодногоОтпуска.СпособРасчетаОстаткаОтпуска 
            ИНАЧЕ ТекущиеКадровыеДанныеСотрудников.СпособРасчетаОтпусковПоТрудовомуДоговору 
        КОНЕЦ = ЗНАЧЕНИЕ(Перечисление.СпособыРасчетаОстаткаОтпуска.ПоРабочимДням) 
    ТОГДА КоличествоДнейВПериодах.КоличествоРабочихДнейВПериоде 
    ИНАЧЕ КоличествоДнейВПериодах.КоличествоКалендарныхДнейВПериоде 
КОНЕЦ КАК КоличествоДнейВПериоде

На первый взгляд конструкция кажется избыточной и запутанной из-за того, что ключевое слово КОНЕЦ внутреннего блока соседствует с оператором сравнения =. Давайте разберем эту структуру по слоям.

Шаг 1: Выделяем внутреннюю логику

Первое, что нам нужно сделать — это понять, какое значение возвращает внутренний ВЫБОР. Он отвечает за определение приоритетного способа расчета. Проанализируем это условие:

  1. Проверяется поле ТаблицаДанных.ОтборПоВидуЕжегодногоОтпуска. Если оно заполнено (не равно ПустаяСсылка), то система берет настройку непосредственно из этого вида отпуска: СпособРасчетаОстаткаОтпуска.
  2. Если вид отпуска не указан, система обращается к кадровым данным сотрудника и берет настройку из его трудового договора: СпособРасчетаОтпусковПоТрудовомуДоговору.

Результатом работы этого внутреннего блока всегда будет значение перечисления СпособыРасчетаОстаткаОтпуска.

Шаг 2: Внешнее сравнение

Теперь посмотрим, что происходит дальше. Результат, полученный на первом шаге, сравнивается со значением ЗНАЧЕНИЕ(Перечисление.СпособыРасчетаОстаткаОтпуска.ПоРабочимДням). Именно здесь кроется визуальная ловушка: КОНЕЦ внутреннего выбора — это просто завершение выражения, значение которого мы тут же начинаем сравнивать.

Если условие выполняется (т.е. расчет ведется по рабочим дням), запрос выбирает поле КоличествоРабочихДнейВПериоде. Во всех остальных случаях (как правило, это расчет по календарным дням) выбирается КоличествоКалендарныхДнейВПериоде.

Шаг 3: Перевод на язык «Если... Тогда»

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


// Сначала определяем способ расчета (внутренний ВЫБОР)
ПеременнаяСпособРасчета = "";
Если НЕ ТаблицаДанных.ОтборПоВидуЕжегодногоОтпуска.Пустая() Тогда
    ПеременнаяСпособРасчета = ТаблицаДанных.ОтборПоВидуЕжегодногоОтпуска.СпособРасчетаОстаткаОтпуска;
Иначе
    ПеременнаяСпособРасчета = ТекущиеКадровыеДанныеСотрудников.СпособРасчетаОтпусковПоТрудовомуДоговору;
КонецЕсли;

// Теперь определяем итоговое количество дней (внешний ВЫБОР)
Если ПеременнаяСпособРасчета = Перечисления.СпособыРасчетаОстаткаОтпуска.ПоРабочимДням Тогда
    КоличествоДнейВПериоде = КоличествоДнейВПериодах.КоличествоРабочихДнейВПериоде;
Иначе
    КоличествоДнейВПериоде = КоличествоДнейВПериодах.КоличествоКалендарныхДнейВПериоде;
КонецЕсли;

Важные нюансы и подводные камни

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

1. Обработка значений NULL
В тексте сообщения фигурирует проверка на ПустаяСсылка. Однако, если ТаблицаДанных соединена левым соединением, поле ОтборПоВидуЕжегодногоОтпуска может содержать NULL. В языке запросов 1С сравнение NULL = ПустаяСсылка вернет ЛОЖЬ (или NULL в зависимости от контекста), и логика может пойти по ветке ИНАЧЕ некорректно. Рекомендуется использовать функцию ЕСТЬNULL перед сравнением.

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


ВЫБОР
    КОГДА (Внутренний_Выбор) = Значение
    ТОГДА ...
ИНАЧЕ ...
КОНЕЦ

Хотя скобки вокруг внутреннего выбора технически не запрещены для выделения выражения, чаще всего их не ставят, что и создает трудности при чтении.

Рекомендации по оптимизации

Если вы проектируете сложный отчет и понимаете, что количество вложенных ВЫБОР растет, рассмотрите возможность использования Временных Таблиц.

Вместо того чтобы городить многоэтажные конструкции, можно в первой временной таблице вычислить «Способ расчета», а во второй уже использовать готовое значение для выбора нужного поля с днями. Это не только сделает код чище, но и упростит отладку в Консоли запросов, так как вы сможете проверить промежуточный результат на каждом этапе.

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

← На главную