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