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

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

Как в запросе 1С ограничить тип документа

Как в запросе 1С ограничить тип документа: ССЫЛКА, ТИПЗНАЧЕНИЯ, ВЫРАЗИТЬ, РАЗНОСТЬДАТ. Примеры кода, сравнение способов, типичные ошибки и FAQ.

При разработке отчётов и обработок в 1С часто встречается задача: в регистре или таблице хранятся ссылки на документы разных типов, а нужны данные только по конкретному виду — например, только по «Реализация товаров и услуг» или только по «Поступление товаров». Если не ограничить тип, запрос вернёт лишние строки, а соединения и обращения к реквизитам через точку могут дать ошибки или пустые значения.

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

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

Зачем ограничивать тип документа в запросе

Регистры накопления, сведений и бухгалтерии в типовых конфигурациях почти всегда имеют измерение или реквизит «Регистратор» составного типа: одним регистром двигаются десятки видов документов. Когда вы строите отчёт по продажам, вас интересуют только движения, сделанные документами реализации, а не корректировками, возвратами или перемещениями.

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

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

Способ 1. Условие ССЫЛКА — самый простой вариант

Оператор ССЫЛКА проверяет, что значение поля является ссылкой на объект указанного типа. Это самый читаемый и чаще всего оптимальный способ ограничить документы одним видом.

ВЫБРАТЬ

Продажи.Регистратор КАК Документ,

СУММА(Продажи.СуммаОборот) КАК Сумма

ИЗ

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

ГДЕ

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

СГРУППИРОВАТЬ ПО

Продажи.Регистратор

Здесь в выборку попадут только обороты, сформированные документами «Реализация товаров услуг». Все прочие регистраторы будут отброшены ещё на этапе выполнения условия.

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

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

Функция ТИПЗНАЧЕНИЯ() возвращает тип значения поля, а функция ТИП() формирует тип для сравнения. Этот вариант удобен, когда нужно проверить тип не только ссылки, но и любого составного поля — например, реквизита «ДокументОснование».

ВЫБРАТЬ

Оплаты.ДокументОснование КАК Основание,

Оплаты.Сумма КАК Сумма

ИЗ

Документ.ОплатаОтПокупателя КАК Оплаты

ГДЕ

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

Запрос вернёт только те оплаты, у которых основанием является именно «Реализация товаров услуг», а не счёт на оплату или заказ клиента.

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

Способ 3. Оператор ВЫРАЗИТЬ — приведение составного типа

Оператор ВЫРАЗИТЬ() приводит значение составного поля к указанному типу. Если фактический тип не совпадает — результатом будет NULL. Это позволяет одновременно ограничить тип и безопасно обратиться к реквизитам документа.

ВЫБРАТЬ

ВЫРАЗИТЬ(Расчёты.Регистратор КАК Документ.РеализацияТоваровУслуг) КАК Реализация,

Расчёты.СуммаОстаток КАК Долг

ИЗ

РегистрНакопления.РасчётыСКонтрагентами.Остатки КАК Расчёты

ГДЕ

ВЫРАЗИТЬ(Расчёты.Регистратор КАК Документ.РеализацияТоваровУслуг) ЕСТЬ НЕ NULL

После приведения можно обращаться к реквизитам документа через точку: Реализация.Контрагент, Реализация.Договор. Такие обращения будут корректны, потому что тип поля уже сужен до одного документа.

Способ 4. Параметр-ссылка и отбор по конкретному документу

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Движения.Номенклатура КАК Номенклатура,

| Движения.Количество КАК Количество

|ИЗ

| РегистрНакопления.ТоварыНаСкладах КАК Движения

|ГДЕ

| Движения.Регистратор = &Регистратор";

Запрос.УстановитьПараметр("Регистратор", ДокументСсылка);

Для списка документов одного вида передайте массив ссылок и используйте условие В (&СписокДокументов). Это быстрее, чем перечисление условий через ИЛИ, и удобнее сопровождать.

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

Когда нужны два-три вида документов, условия объединяются через ИЛИ. Чтобы не повторять длинные конструкции, удобно сгруппировать их скобками.

ГДЕ

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

ИЛИ Продажи.Регистратор ССЫЛКА Документ.КорректировкаРеализации

ИЛИ Продажи.Регистратор ССЫЛКА Документ.ВозвратТоваровОтПокупателя)

Альтернатива — собрать нужные ссылки во временную таблицу и соединиться с ней. Такой подход выигрывает, когда список видов документов формируется динамически, например по настройкам отчёта.

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

Как выбрать способ

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

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

После написания запроса проверьте его в консоли запросов: убедитесь, что в выборку попали документы только нужного вида и что реквизиты, к которым вы обращаетесь через точку, заполнены, а не содержат NULL.

Ошибки в этой теме повторяются из проекта в проект. Разберём самые частые.

Типичные ошибки
01
Сравнение типа строкой: ТИПЗНАЧЕНИЯ(Поле) = "Документ.Реализация" — тип нельзя сравнить со строкой, нужен ТИП(Документ.Имя)
02
Обращение к реквизиту через точку без ограничения типа — для документов без такого реквизита получите NULL и потеряете строки при соединениях
03
Опечатка в имени документа в ТИП() — запрос падает с ошибкой ещё на этапе компиляции, проверяйте имя в конфигураторе
04
Использование ВЫРАЗИТЬ в условии соединения — приводит к полному перебору таблицы и тайм-аутам на больших базах
05
Отбор по типу в итоговом запросе вместо временной таблицы — фильтрация выполняется позже, чем могла бы, и замедляет отчёт

Ещё одна тонкость: в виртуальных таблицах оборотов и остатков поле «Регистратор» доступно не всегда. Например, у таблицы Обороты регистра накопления регистратор появляется только если задать периодичность «Регистратор» или «Запись». Проверяйте доступность поля в конструкторе запроса.

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

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

Состав выборки
Норма

Все строки содержат документы только нужного вида

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

В результате встречаются другие виды документов или пустые ссылки

Реквизиты через точку
Норма

Поля заполнены значениями

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

Поля содержат NULL — тип не ограничен или реквизита нет у части документов

Скорость выполнения
Норма

Запрос выполняется за приемлемое время на рабочей базе

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

Запрос зависает — вероятно, ВЫРАЗИТЬ или ТИПЗНАЧЕНИЯ использованы в соединении

Количество строк
Норма

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

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

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

Часто задаваемые вопросы

Чем отличается ССЫЛКА от ТИПЗНАЧЕНИЯ в запросе?

Оператор ССЫЛКА проверяет, что значение является ссылкой заданного вида, и работает только со ссылочными типами. ТИПЗНАЧЕНИЯ возвращает тип любого значения и сравнивается с ТИП(...). Для ссылок на документы предпочтительнее ССЫЛКА — она короче и обычно эффективнее.

Можно ли ограничить тип документа в параметрах виртуальной таблицы?

Напрямую отобрать по виду регистратора в параметрах виртуальной таблицы нельзя — там доступны только период и условия по измерениям. Ограничивайте тип в секции ГДЕ основного запроса либо через временную таблицу с отобранными регистраторами.

Как отобрать документы всех видов, кроме одного?

Используйте отрицание: ГДЕ НЕ Регистратор ССЫЛКА Документ.ИмяДокумента. Учтите, что условие с НЕ обычно не использует индексы, поэтому на больших таблицах проверяйте скорость выполнения.

Почему ВЫРАЗИТЬ возвращает NULL, хотя тип вроде бы правильный?

Чаще всего имя документа в ВЫРАЗИТЬ не совпадает с фактическим типом значения — например, указана «РеализацияТоваров», а в базе документ называется «РеализацияТоваровУслуг». Сверьте имя объекта в конфигураторе и проверьте значение поля через ТИПЗНАЧЕНИЯ.

Работает ли ограничение типа в СКД и динамических списках?

Да. В СКД те же операторы ССЫЛКА, ТИПЗНАЧЕНИЯ и ВЫРАЗИТЬ доступны в тексте запроса набора данных и в отборах. В динамических списках ограничение по типу задаётся в произвольном запросе списка, а в отборах пользователя — через сравнение с конкретной ссылкой.

Как ограничить тип в поле компоновки «Регистратор» при выводе отчёта?

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

Итог

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

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