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