Разработка и Конфигурация · 11 мин
Запрос 1С: как отобрать записи по типу документа
Как в запросе 1С отобрать записи по типу документа: функция ТИПЗНАЧЕНИЯ, сравнение ССЫЛКА, оператор ВЫРАЗИТЬ, работа с составными типами и типичные ошибки.
Отбор по типу документа — одна из самых частых задач при написании запросов в 1С. Она возникает, когда поле регистра, табличной части или реквизита имеет составной тип и может хранить ссылки на разные документы: реализацию товаров, поступление, счёт-фактуру и так далее. Без корректного отбора по типу выборка либо возвращает лишние данные, либо теряет нужные строки.
В языке запросов 1С для работы с типами есть три основных инструмента: функция ТИПЗНАЧЕНИЯ(), оператор сравнения ССЫЛКА и оператор приведения ВЫРАЗИТЬ(). У каждого своё назначение, свои ограничения и своё влияние на производительность. Ниже разобраны все три способа с примерами, а также смежные задачи: получение представления типа, работа с полем «Документ» в наборах записей и проверка результата.
Когда возникает задача отбора по типу документа
Составной тип встречается в типовых конфигурациях повсеместно. Типичные примеры: измерение или реквизит «Документ» в регистрах сведений (например, хранение привязки файлов или статусов), поле «ДокументОснование», реквизиты расчётных регистров, поля «Сделка» и «Регистратор» в движениях. Во всех этих местах одна колонка может содержать ссылки на десятки разных видов документов.
Практические сценарии, где без отбора по типу не обойтись: построение отчёта по всем документам определённого вида через универсальный регистр, поиск документов-оснований конкретного типа, выгрузка данных, где требуется отфильтровать только «Реализацию товаров и услуг» из смешанного списка ссылок. Ещё одна частая ситуация — обработка результата запроса, когда нужно понять, с каким именно документом связана строка.
Важно понимать ограничение: проверка типа выполняется на уровне ссылки, а не данных документа. То есть запрос отвечает на вопрос «ссылка какого вида хранится в поле», а не «проведён ли документ» или «какая у него организация». Для условий по реквизитам сначала приводят тип через ВЫРАЗИТЬ, а затем обращаются к полям.
Способ 1. Функция ТИПЗНАЧЕНИЯ и литерал ТИП
Классический вариант — функция ТИПЗНАЧЕНИЯ(), которая возвращает тип значения поля, и литерал ТИП(), задающий конкретный тип для сравнения. Условие выглядит так:
ВЫБРАТЬ
Статусы.Документ КАК Документ
ИЗ
РегистрСведений.СтатусыДокументов КАК Статусы
ГДЕ
ТИПЗНАЧЕНИЯ(Статусы.Документ) = ТИП(Документ.РеализацияТоваровУслуг)
Функция подходит и для проверки нескольких типов через ИЛИ или через список В. Например, отобрать строки, где документ — либо реализация, либо возврат: ТИПЗНАЧЕНИЯ(Поле) В (ТИП(Документ.РеализацияТоваровУслуг), ТИП(Документ.ВозвратТоваровОтПокупателя)).
Главный недостаток способа — производительность. СУБД не всегда может использовать индекс для условия с функцией, поэтому на больших таблицах запрос с ТИПЗНАЧЕНИЯ может работать заметно медленнее аналога со ССЫЛКА. Для разовых выборок и небольших регистров разница незаметна, для регламентных операций по миллионам записей — критична.
Способ 2. Оператор ССЫЛКА — быстрая проверка типа
Оператор ССЫЛКА проверяет, является ли значение поля ссылкой на объект указанного типа. Синтаксис компактнее и обычно эффективнее:
ВЫБРАТЬ
Статусы.Документ КАК Документ
ИЗ
РегистрСведений.СтатусыДокументов КАК Статусы
ГДЕ
Статусы.Документ ССЫЛКА Документ.РеализацияТоваровУслуг
Оператор возвращает булево значение, поэтому его можно использовать не только в секции ГДЕ, но и в списке выборки или в ВЫБОР. Например, пометить строки признаком: ВЫБОР КОГДА Поле ССЫЛКА Документ.СчетФактура ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ КОНЕЦ КАК ЭтоСчетФактура.
Ограничение: ССЫЛКА работает только со ссылочными типами. Для примитивных типов (число, строка, дата) оператор неприменим — там остаётся ТИПЗНАЧЕНИЯ с литералами ТИП(ЧИСЛО), ТИП(СТРОКА) и т.д. Также ССЫЛКА не поддерживает перечисление нескольких типов в одном условии, приходится соединять проверки через ИЛИ.
Сравнение способов проверки типа
Универсально, работает и с примитивными типами, удобно для списка типов через В. Может быть медленнее на больших таблицах.
Короткая запись, обычно быстрее, возвращает булево. Только ссылочные типы, по одному типу за раз.
Не фильтр, а приведение типа: нужен для доступа к реквизитам конкретного документа. Часто комбинируется с фильтром.
Способ 3. ВЫРАЗИТЬ — приведение типа и доступ к реквизитам
Оператор ВЫРАЗИТЬ() не фильтрует записи, а приводит значение составного поля к указанному типу. Если значение в строке другого вида — результатом будет NULL. Это позволяет решать две задачи: обращаться к реквизитам конкретного документа и одновременно отсеивать чужие типы через проверку на NULL.
ВЫБРАТЬ
ВЫРАЗИТЬ(Статусы.Документ КАК Документ.РеализацияТоваровУслуг) КАК Реализация
ИЗ
РегистрСведений.СтатусыДокументов КАК Статусы
ГДЕ
НЕ ВЫРАЗИТЬ(Статусы.Документ КАК Документ.РеализацияТоваровУслуг) ЕСТЬ NULL
После приведения становятся доступны реквизиты документа: ВЫРАЗИТЬ(Поле КАК Документ.РеализацияТоваровУслуг).Организация. Без приведения обращение к реквизиту составного поля через точку привело бы к неявному соединению со всеми таблицами документов составного типа — это одна из самых тяжёлых операций в запросах 1С и частая причина «зависающих» отчётов.
Рекомендуемый шаблон для отчётов: сначала явно привести поле к нужному типу в отдельном поле выборки, затем работать с этим псевдонимом. Так запрос остаётся читаемым, а план выполнения — предсказуемым.
Отбор по регистратору и полю «Документ» в движениях
Отдельный частный случай — отбор движений по типу регистратора. У регистров накопления и бухгалтерии поле Регистратор всегда ссылочное, и его тип совпадает с видом документа, создавшего запись. Здесь работают те же приёмы:
ВЫБРАТЬ
Остатки.Регистратор КАК Регистратор,
Остатки.Количество КАК Количество
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК Остатки
ГДЕ
Остатки.Регистратор ССЫЛКА Документ.ПеремещениеТоваров
Для виртуальных таблиц (остатки, обороты) фильтр по регистратору лучше задавать в параметрах виртуальной таблицы, а не в секции ГДЕ — тогда отбор выполнится до расчёта виртуальной таблицы и запрос отработает быстрее. Однако условие по типу регистратора в параметры виртуальной таблицы передаётся не всегда эффективно; на практике надёжнее отбирать по конкретным ссылкам или по периоду, а тип проверять в ГДЕ.
- 1Определите, какое поле имеет составной тип, и посмотрите его состав в конфигураторе.
- 2Выберите способ: ССЫЛКА — для простого фильтра, ТИПЗНАЧЕНИЯ — для списка типов или примитивов, ВЫРАЗИТЬ — если нужны реквизиты документа.
- 3Добавьте условие в секцию ГДЕ или параметры виртуальной таблицы.
- 4Если обращаетесь к реквизитам документа, сначала приведите поле через ВЫРАЗИТЬ.
- 5Выполните запрос в консоли запросов и сверьте количество строк с ожидаемым.
Проверка результата и типичные ошибки
После написания запроса проверку удобно делать в консоли запросов на копии базы или на тестовом периоде. Контрольные точки: количество строк не должно быть нулевым при заведомо существующих документах; в выборке не должно быть ссылок других видов; поля, полученные через ВЫРАЗИТЬ, не должны массово содержать NULL (это признак того, что тип указан неверно).
Чтобы увидеть тип значения в результате запроса для отладки, добавьте в список выборки ТИПЗНАЧЕНИЯ(Поле) КАК ТипПоля. При программной обработке результата конкретный тип проверяется через ТипЗнч(Строка.Документ) = Тип("ДокументСсылка.РеализацияТоваровУслуг").
Как проверить результат
Совпадает с числом документов нужного вида за период
Ноль строк при существующих документах — проверьте имя типа и вид поля
Все ссылки относятся к нужному виду документа
Есть другие виды — условие не сработало или поле перепутано
Заполнены значениями реквизитов
Сплошные NULL — указан неверный тип приведения
Производительность и ограничения
На файловых базах и небольших таблицах разница между ТИПЗНАЧЕНИЯ и ССЫЛКА практически незаметна, выбирайте по читаемости. На клиент-серверных базах с миллионами записей предпочтителен ССЫЛКА, а ещё лучше — предварительный отбор по другим индексированным полям (период, организация), чтобы проверка типа применялась к уже сокращённому набору строк.
Помните про ограничения платформы: литерал ТИП() не принимает параметры, имя документа должно быть известно на момент написания запроса. Динамический отбор «по типу, переданному параметром» напрямую в запросе невозможен — приходится либо формировать текст запроса программно, либо использовать схему компоновки данных с отбором по полю типа, либо фильтровать результат уже в коде.
Если отбор по типу документа нужен в отчёте на СКД, не пишите условие в тексте запроса — добавьте вычисляемое поле с ТИПЗНАЧЕНИЯ или отбор по условию ССЫЛКА в настройках. Так пользователь сможет сам менять вид документа без правки запроса.
Часто задаваемые вопросы
Можно ли передать тип документа в запрос параметром?
Напрямую нет: литерал ТИП() не принимает параметры. Обходные пути — программная подстановка имени документа в текст запроса перед выполнением, отбор по конкретным ссылкам через параметр-список или фильтрация результата в коде через ТипЗнч().
Чем ССЫЛКА отличается от ТИПЗНАЧЕНИЯ на практике?
Оба проверяют тип значения поля. ССЫЛКА короче, возвращает булево и обычно быстрее, но работает только со ссылочными типами и по одному типу за раз. ТИПЗНАЧЕНИЯ универсальнее: подходит для примитивов и для проверки списка типов через В.
Почему запрос с ВЫРАЗИТЬ возвращает NULL в поле документа?
NULL означает, что значение в этой строке имеет другой тип, чем указано в ВЫРАЗИТЬ. Это нормальное поведение оператора. Чтобы оставить только строки нужного типа, добавьте условие НЕ ВЫРАЗИТЬ(...) ЕСТЬ NULL или совместите с фильтром ССЫЛКА.
Как отобрать документы нескольких видов одновременно?
Через список: ТИПЗНАЧЕНИЯ(Поле) В (ТИП(Документ.Вид1), ТИП(Документ.Вид2)), либо цепочкой условий Поле ССЫЛКА Документ.Вид1 ИЛИ Поле ССЫЛКА Документ.Вид2. Первый вариант компактнее, второй иногда быстрее.
Работает ли отбор по типу для регистратора виртуальной таблицы остатков?
Проверка типа регистратора работает в секции ГДЕ итогового запроса. В параметрах виртуальной таблицы условие по типу регистратора лучше не использовать — эффективнее ограничивать период и измерения, а тип проверять после расчёта виртуальной таблицы.
Как узнать тип значения поля в коде после выполнения запроса?
Используйте функцию ТипЗнч() для значения из выборки и сравнивайте с Тип("ДокументСсылка.ИмяДокумента"). Альтернатива — вывести ТИПЗНАЧЕНИЯ(Поле) отдельным полем запроса и анализировать его при обходе результата.
Что важно запомнить
Фильтр по типу документа строится на трёх инструментах: ССЫЛКА — быстрый отбор по одному виду, ТИПЗНАЧЕНИЯ — универсальная проверка и списки типов, ВЫРАЗИТЬ — приведение типа для доступа к реквизитам. Никогда не обращайтесь к реквизитам составного поля без приведения типа и всегда проверяйте выборку на тестовых данных.