Как правильно задать условие для вида расчета в запросе 1С при использовании функции ВЫБОР?

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

При разработке отчетов в системе 1С:Предприятие программисты часто сталкиваются с необходимостью динамического изменения логики расчета в зависимости от вида начисления. Типичная ошибка начинающих разработчиков — попытка сравнить ссылочный тип данных (например, ВидРасчета) со строковым литералом напрямую в тексте запроса. Разберем подробно, почему так делать нельзя и какие существуют правильные способы решения этой задачи.

Суть проблемы: Сравнение ссылки со строкой

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

ВЫБОР КОГДА ВидРасчета = "Отпуск" ТОГДА ... КОНЕЦ

приведет к ошибке или некорректной работе отчета. Это происходит потому, что поле ВидРасчета в регистре расчета содержит Ссылку (уникальный идентификатор записи в таблице плана видов расчета), а "Отпуск" — это просто Строка. Система не может сравнить эти два разных типа данных.

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

Способ №1: Использование функции ЗНАЧЕНИЕ()

Проанализируем самый эффективный и быстрый способ — использование функции ЗНАЧЕНИЕ(). Этот метод идеально подходит, если вид расчета является предопределенным (то есть созданным в конфигураторе).

Рассмотрим пример кода в запросе:


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

Преимущества этого метода:

  1. Производительность: Сравнение происходит на уровне СУБД по внутреннему идентификатору ссылки.
  2. Лаконичность: Не нужно передавать дополнительные параметры из кода на встроенном языке.
  3. Надежность: Даже если пользователь изменит наименование вида расчета в режиме «Предприятие», запрос продолжит работать корректно, так как он привязан к внутреннему имени объекта.

Способ №2: Передача значения через параметр запроса

Если вид расчета не является предопределенным или он выбирается пользователем на форме отчета, нам необходимо использовать параметры. Посмотрим, как это реализовать по шагам.

Сначала в тексте запроса мы указываем имя параметра через символ &:


ВЫБОР
    КОГДА ОсновныеНачисления.ВидРасчета = &НужныйВидРасчета
        ТОГДА ОсновныеНачисления.КалендарныеДниФактическийПериодДействия
    ИНАЧЕ ОсновныеНачисления.ЗначениеДниФактическийПериодДействия
КОНЕЦ КАК Дни

Затем во встроенном языке (в модуле обработки или отчета) мы должны установить этот параметр. Рассмотрим пример поиска ссылки по наименованию (хотя это не самый рекомендуемый метод, он часто используется):


СсылкаНаОтпуск = ПланыВидовРасчета.Начисления.НайтиПоНаименованию("Отпуск");
Запрос.УстановитьПараметр("НужныйВидРасчета", СсылкаНаОтпуск);

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

Способ №3: Обращение к реквизитам через точку (Наименование)

Иногда разработчики используют конструкцию ВидРасчета.Наименование = "Отпуск". Разберем, почему этот вариант считается «плохим тоном».

При обращении через точку в языке запросов 1С происходит неявное левое соединение (LEFT JOIN) с таблицей Плана видов расчета. Если записей в регистре миллионы, это существенно замедляет выполнение отчета. Кроме того, сравнение строк всегда медленнее, чем сравнение ссылок. Используйте этот метод только в крайнем случае, если нет возможности получить ссылку напрямую.

Оптимизация работы с регистрами расчета

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

Сравним два подхода:

Плохо: ИЗ РегистрРасчета.Начисления КАК Таблица ГДЕ Таблица.ПериодРегистрации = &Период

Хорошо: ИЗ РегистрРасчета.Начисления(&Период) КАК Таблица

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

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

В запросе автора при объединении данных из ДополнительныеНачисления и Удержания в поле «Дни» подставляется NULL. Проанализируем последствия: если этот отчет будет использоваться в СКД для расчета итогов, NULL может вызвать ошибки при суммировании или привести к пустому результату.

Рекомендация: Для числовых показателей в объединяемых запросах лучше использовать 0 вместо NULL. Это обеспечит корректное приведение типов данных:

ВЫБРАТЬ Сотрудник, Результат, 0 КАК Дни ИЗ РегистрРасчета.Удержания ГДЕ ...

Подведем итоги

Для корректной работы условия ВЫБОР в запросах 1С необходимо придерживаться следующих правил:

  1. Всегда сравнивать ссылку со ссылкой. Избегайте сравнения ВидРасчета = "Строка".
  2. Использовать ЗНАЧЕНИЕ() для предопределенных элементов конфигурации.
  3. Использовать параметры для элементов, созданных пользователями.
  4. Минимизировать обращения через точку (к наименованию или коду) для сохранения высокой скорости работы отчета.
  5. Проверять метаданные: Помните, что поля типа КалендарныеДниФактическийПериодДействия будут заполнены только в том случае, если у вида расчета в конфигураторе включена настройка «Использовать период действия».

Соблюдение этих принципов позволит вам создавать стабильные и быстрые отчеты, которые не «сломаются» при обновлении базы или переименовании элементов пользователями.

← На главную