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

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

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

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

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

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

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

Как устроено сравнение типов в языке запросов 1С

Язык запросов 1С не позволяет напрямую сравнить значение с типом через обычный оператор равенства: конструкция ГДЕ Документ = ТИП(Документ.РеализацияТоваровУслуг) синтаксически невозможна, потому что слева находится ссылка, а справа — значение типа «Тип». Это разные виды данных, и сравнение либо вернёт ложь, либо вызовет ошибку.

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

Важно понимать, где вообще возникает задача сравнения типа. Чаще всего это регистры накопления и сведений с измерениями составного типа (например, «ДокументРасчетов» может хранить ссылки на разные виды документов), документы с реквизитами-основаниями составного типа и табличные части, где поле может ссылаться на разные объекты. Если поле имеет единственный тип документа, сравнение типа не нужно вовсе.

Способ 1: сравнение через ТИПЗНАЧЕНИЯ и ТИП

Основной и самый универсальный способ — сравнить результат функции ТИПЗНАЧЕНИЯ со значением ТИП. Конструкция выглядит так:

ВЫБРАТЬ

Взаиморасчеты.ДокументРасчетов КАК ДокументРасчетов

ИЗ

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

ГДЕ

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

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

Для отбора нескольких видов документов используется перечисление через ИЛИ или оператор В со списком значений типов:

ГДЕ

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

Способ 2: условие ССЫЛКА для ссылочных полей

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

ВЫБРАТЬ

Расчеты.ДокументРасчетов КАК ДокументРасчетов

ИЗ

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

ГДЕ

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

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

Сравнение вариантов

ТИПЗНАЧЕНИЯ(Поле) = ТИП(...)

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

Поле ССЫЛКА Документ.Имя

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

ВЫРАЗИТЬ(Поле КАК Документ.Имя)

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

Как получить реквизиты документа составного поля через ВЫРАЗИТЬ

Частая сопутствующая задача: поле составного типа, и нужно не только отобрать записи по виду документа, но и вывести его реквизит, например организацию или контрагента. Напрямую обратиться к реквизиту составного поля нельзя — запрос не знает, какой из возможных типов там хранится. Решение — приведение через ВЫРАЗИТЬ:

ВЫБРАТЬ

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

ИЗ

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

ГДЕ

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

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

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

Иногда тип нужно не отфильтровать, а показать: например, в отчёте вывести колонку «Вид документа». Для этого ТИПЗНАЧЕНИЯ помещают в список выборки:

ВЫБРАТЬ

ТИПЗНАЧЕНИЯ(Расчеты.ДокументРасчетов) КАК ТипДокумента,

Расчеты.ДокументРасчетов КАК ДокументРасчетов

ИЗ

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

В результате колонка будет содержать значение типа «Тип». Если нужна читаемая строка, значение типа обрабатывают уже на встроенном языке после выполнения запроса или используют представление ссылки. Учтите: группировка и соединения по значению типа допустимы, что удобно для сводных отчётов по видам документов.

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

Как проверить, что запрос работает правильно

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

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

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

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

Состав результата
Норма

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

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

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

Имя документа в запросе
Норма

Имя совпадает с именем объекта в конфигураторе, запрос проходит проверку

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

Ошибка «Поле не найдено» или неверное имя типа при выполнении

Реквизиты через ВЫРАЗИТЬ
Норма

Для записей нужного типа реквизиты заполнены

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

Все значения реквизитов NULL — тип в ВЫРАЗИТЬ не совпадает с данными

Типичные ошибки при сравнении типа документа

Первая и самая распространённая ошибка — попытка сравнить ссылку со строкой: ГДЕ Документ = "РеализацияТоваровУслуг". Ссылка никогда не равна строке, такой запрос вернёт пустой результат без какой-либо ошибки, что затрудняет диагностику. Вторая ошибка — использование синонима документа вместо имени метаданных в ТИП: синоним может содержать пробелы и отличаться от имени.

Третья группа ошибок связана с составными полями: обращение к реквизиту составного поля без ВЫРАЗИТЬ, сравнение типа несоставного поля (что бессмысленно и замедляет запрос) и забытый отбор по типу перед обращением к реквизитам, из-за чего запрос сканирует лишние таблицы.

Типичные ошибки
01
Сравнение ссылки со строкой «Документ.Реализация...» — результат всегда пустой, ошибки не возникает.
02
Использование синонима вместо имени метаданных в ТИП(Документ.Имя) — запрос не проходит проверку или не находит тип.
03
Обращение к реквизиту составного поля без ВЫРАЗИТЬ — ошибка построения запроса.
04
Отсутствие отбора по типу перед ВЫРАЗИТЬ на больших регистрах — лишние обращения к таблицам и медленное выполнение.
05
Сравнение типа у поля с единственным типом — лишнее вычисление, которое ничего не даёт.

Альтернативы: когда запрос не нужен

Если тип документа нужно проверить не в выборке, а в коде при обработке одной ссылки, запрос вообще не требуется. На встроенном языке используют функцию ТипЗнч(Ссылка) и сравнение с Тип("ДокументСсылка.РеализацияТоваровУслуг") — это быстрее и проще, чем выполнение запроса ради одной проверки.

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

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

Как выбрать действие

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

Частые вопросы

Можно ли сравнить тип документа со строкой в запросе?

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

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

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

Как отобрать записи, где тип документа — любой, кроме одного?

Используйте отрицание: ГДЕ НЕ Поле ССЫЛКА Документ.ИмяДокумента, либо ТИПЗНАЧЕНИЯ(Поле) <> ТИП(Документ.ИмяДокумента). Учтите, что записи с NULL в поле в результат не попадут — при необходимости добавьте условие ИЛИ Поле ЕСТЬ NULL.

Почему запрос с ВЫРАЗИТЬ возвращает NULL в реквизитах?

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

Работает ли сравнение типа для регистратора в таблице движений?

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

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

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

Итог

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

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