Как в запросе 1С ограничить выборку только двумя типами документов-регистраторов?

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

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

Способ 1. Использование оператора ССЫЛКА

Самый распространенный и читаемый способ — использование встроенного оператора ССЫЛКА. Этот оператор проверяет, относится ли ссылка в поле Регистратор к конкретному метаданному документу. Рассмотрим пример, когда нам нужно оставить только «Реализацию товаров и услуг» и «Поступление товаров и услуг».

Разберем по шагам написание условия:


ГДЕ
    Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
    ИЛИ Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг

Этот метод считается «каноническим» в среде разработчиков 1С. Основное преимущество заключается в том, что SQL-сервер при выполнении такого запроса проверяет только идентификатор типа в поле ссылки, что работает достаточно быстро. Однако стоит помнить, что при использовании большого количества условий ИЛИ производительность может снизиться из-за особенностей построения плана запроса СУБД.

Способ 2. Использование функции ТИПЗНАЧЕНИЯ и оператора ТИП

Иногда удобнее использовать функцию ТИПЗНАЧЕНИЯ. Это бывает полезно, если вы хотите использовать оператор В для проверки вхождения в список типов, что делает код более компактным.

Рассмотрим пример:


ГДЕ
    ТИПЗНАЧЕНИЯ(Регистратор) В (ТИП(Документ.РеализацияТоваровУслуг), ТИП(Документ.ПоступлениеТоваровУслуг))

Проанализируем ситуацию: хотя результат выполнения будет идентичен первому способу, использование оператора В с перечислением типов часто работает стабильнее, чем цепочка ИЛИ, так как СУБД проще оптимизировать такое условие. Важно отметить: в запросе следует писать именно ТИПЗНАЧЕНИЯ(Регистратор), а не ТИПЗНАЧЕНИЯ(Регистратор.Ссылка), так как обращение через точку к полю Ссылка создает лишнее соединение с таблицей документа, что замедляет работу.

Способ 3. Передача массива типов через параметры

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

Пример реализации на языке 1С:


МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("ДокументСсылка.РеализацияТоваровУслуг"));
МассивТипов.Добавить(Тип("ДокументСсылка.ПоступлениеТоваровУслуг"));

Запрос.УстановитьПараметр("МассивТипов", МассивТипов);
Запрос.Текст = "ВЫБРАТЬ * ИЗ РегистрНакопления.Продажи ГДЕ ТИПЗНАЧЕНИЯ(Регистратор) В (&МассивТипов)";

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

Оптимизация: Фильтрация в виртуальных таблицах

Выясним важную деталь: если вы работаете с виртуальными таблицами (например, Обороты или ОстаткиИОбороты), крайне не рекомендуется ставить условие по регистратору в блоке ГДЕ. Это критическая ошибка новичков.

Правильный подход: условие нужно указывать непосредственно в параметрах виртуальной таблицы. Рассмотрим на примере таблицы Продажи.Обороты:


ВЫБРАТЬ
    ПродажиОбороты.Период,
    ПродажиОбороты.Регистратор,
    ПродажиОбороты.СуммаОборот
ИЗ
    РегистрНакопления.Продажи.Обороты(,, Регистратор, Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг) КАК ПродажиОбороты

Почему это важно? Когда условие находится в параметрах виртуальной таблицы, платформа 1С формирует максимально эффективный SQL-запрос, который отсекает ненужные данные еще на этапе выборки из базы. Если же условие стоит в ГДЕ, система может сначала выбрать все записи регистра, а потом начать их фильтровать, что на больших объемах данных приведет к зависанию системы.

Особенности работы SQL при обращении к регистратору

Давайте проанализируем, что происходит «под капотом». Поле Регистратор является составным. На уровне СУБД это означает, что таблица регистра содержит поля для каждого типа документа (так называемый LEFT JOIN со всеми возможными таблицами документов).

Основные нюансы:

  1. Сканирование таблиц: Чем больше типов документов может выступать регистратором, тем «тяжелее» запрос. Поэтому фильтрация по типу — это не просто удобство, а необходимость для поддержания скорости базы.
  2. Оператор ССЫЛКА: Он наиболее эффективен, так как обращается к внутреннему идентификатору типа ссылки (_TypeID в SQL), не требуя обращения к самим таблицам документов.
  3. Объединение запросов (UNION ALL): В некоторых случаях, если документов много и запрос работает медленно, эффективнее будет сделать два отдельных запроса к регистру (каждый со своим типом документа) и объединить их результаты. Это гарантирует использование индексов по полной программе.

Разница между ССЫЛКА и ТИПЗНАЧЕНИЯ

Хотя в большинстве случаев они взаимозаменяемы, давайте подытожим различия:

Таким образом, для решения задачи автора наиболее подходящим и простым решением будет использование оператора ССЫЛКА в параметрах виртуальной таблицы или через передачу массива типов в параметр ТИПЗНАЧЕНИЯ.

← На главную