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

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

Оператор ВЫРАЗИТЬ КАК Документ в запросах 1С

Как использовать оператор ВЫРАЗИТЬ КАК Документ в запросах 1С: синтаксис, приведение составных типов, соединения по ссылке, типичные ошибки и проверка результата.

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

Типичная ситуация: в регистре накопления измерение или реквизит имеет составной тип (например, «ДокументРасчетовСКонтрагентом», который может быть и «Поступлением товаров», и «Реализацией», и «Платёжным поручением»). Пока поле имеет составной тип, обратиться к реквизиту конкретного документа через точку нельзя — запрос либо не пройдёт проверку в конструкторе, либо вернёт NULL. Приведение типа решает эту задачу.

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

Синтаксис оператора ВЫРАЗИТЬ для документов

Общая форма записи выглядит так:

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

После ключевого слова КАК указывается тип: для документов — Документ. плюс имя вида документа, как оно задано в конфигураторе. Имя чувствительно к точному написанию: если документ называется «РеализацияТоваровУслуг», то «РеализацияТоваров» даст ошибку при проверке запроса.

Приведение возможно только «вниз» по составу типа: поле должно иметь составной тип, включающий указанный документ, либо уже иметь этот тип. Привести документ к справочнику или к несвязанному виду документа нельзя — конструктор запросов выдаст ошибку несовместимости типов.

Результат приведения можно использовать в секциях ВЫБРАТЬ, ГДЕ, СОЕДИНЕНИЕ, а также внутри агрегатных и вложенных выражений. Если фактическое значение поля — документ другого вида, результатом выражения будет NULL, а не ошибка выполнения.

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

Главная практическая цель приведения к документу — разыменование, то есть обращение к реквизитам через точку. Пока поле имеет составной тип, конструктор запросов не покажет реквизиты конкретных документов, а запрос с «незаконным» разыменованием не пройдёт проверку.

Пример: нужно получить контрагента из документа расчётов в регистре «ВзаиморасчетыСКонтрагентами»:

ВЫБРАТЬ

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

СУММА(Взаиморасчеты.Сумма) КАК Сумма

ИЗ

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

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

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

Обратите внимание: если часть записей регистра ссылается на другие виды документов (например, «ПоступлениеТоваровУслуг»), то для этих строк приведённое выражение вернёт NULL, и поле «Контрагент» будет пустым. Такие строки не отбрасываются автоматически — они попадают в результат с NULL-значениями.

Отбор записей по виду документа

Чтобы оставить в результате только конкретный вид документа, приведение типа используют в секции ГДЕ с проверкой на NULL. Условие «приведённое значение не равно NULL» эквивалентно проверке «документ именно этого вида»:

ВЫБРАТЬ

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

Взаиморасчеты.Сумма КАК Сумма

ИЗ

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

ГДЕ

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

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

Сравнение вариантов отбора по виду документа

ВЫРАЗИТЬ(...) <> NULL

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

ССЫЛКА Документ.ВидДокумента

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

ТИПЗНАЧЕНИЯ(Поле) = &Тип

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

Соединение с таблицей документа

Когда к регистру нужно присоединить данные самого документа, приведение типа в условии соединения резко сокращает объём работы СУБД. Без него платформа вынуждена строить соединение со всеми таблицами документов, входящими в составной тип.

ВЫБРАТЬ

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

Реализация.Контрагент КАК Контрагент,

Взаиморасчеты.Сумма КАК Сумма

ИЗ

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

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация

ПО Взаиморасчеты.ДокументРасчетов = Реализация.Ссылка

Внутреннее соединение здесь само по себе отфильтрует записи с другими видами документов — строки, для которых нет пары в таблице «РеализацияТоваровУслуг», в результат не попадут. Если нужно сохранить все записи регистра, используйте ЛЕВОЕ СОЕДИНЕНИЕ: тогда для «чужих» документов поля реализации будут NULL.

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

Порядок добавления приведения типа в запрос
  1. 1
    Определите поле составного типа: в конструкторе запросов посмотрите тип поля — там будет перечислено несколько видов документов.
  2. 2
    Решите, какой вид документа нужен, и напишите ВЫРАЗИТЬ(Поле КАК Документ.ИмяДокумента).
  3. 3
    Если нужны только записи этого вида — добавьте условие ВЫРАЗИТЬ(...) <> NULL в секцию ГДЕ или используйте внутреннее соединение с таблицей документа.
  4. 4
    Обратитесь к реквизитам через точку от приведённого выражения.
  5. 5
    Выполните запрос в консоли запросов на копии базы и проверьте, что суммы и количество строк совпадают с ожиданиями.

Работа с NULL и проверка результата

Приведение типа вводит NULL в результат там, где фактический вид документа отличается. Это влияет на группировки, итоги и последующие вычисления. Например, если группировать по приведённому реквизиту «Контрагент», все «чужие» документы схлопнутся в одну строку с пустым контрагентом — и её легко принять за ошибку данных.

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

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

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

Количество строк до и после приведения
Норма

Без отбора в ГДЕ число строк не изменилось — приведение только добавило NULL

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

Строки пропали, хотя отбор не задан — вероятно, где-то добавилось внутреннее соединение

Поля реквизитов документа
Норма

Для документов нужного вида поля заполнены, для остальных — NULL

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

NULL у всех строк — скорее всего, указан неверный вид документа

Суммы по группировке
Норма

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

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

Появилась строка с пустым ключом и большой суммой — это документы других видов, свалившиеся в NULL

Типичные ошибки и ограничения

Самая частая ошибка — попытка привести поле к виду документа, который не входит в составной тип этого поля. Конструктор запросов в типовых конфигурациях обычно подсвечивает такое несоответствие, но при формировании текста запроса в коде ошибка всплывёт только в момент выполнения.

Вторая ошибка — ожидание, что ВЫРАЗИТЬ отфильтрует записи. Оператор не фильтрует ничего: он лишь меняет трактовку значения. Отбор должен быть описан явно — через ГДЕ, соединение или параметры виртуальной таблицы.

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

Типичные ошибки при работе с ВЫРАЗИТЬ КАК Документ
01
Указан вид документа, не входящий в составной тип поля — запрос падает с ошибкой несовместимости типов.
02
Ожидание автоматического отбора записей — ВЫРАЗИТЬ не фильтрует, для отбора нужно условие в ГДЕ.
03
Опечатка в имени документа — запрос, собранный строкой в коде, упадёт только при выполнении, а не при записи модуля.
04
Многократное разыменование через точку вместо одного соединения с таблицей документа — резкое замедление на больших объёмах.
05
Игнорирование NULL в группировке — строки с другими видами документов сливаются в одну группу с пустым ключом.

Практические рекомендации и альтернативы

Если поле заведомо хранит только один вид документа, правильнее исправить тип на уровне конфигурации — убрать лишние типы из состава. Это избавит от ВЫРАЗИТЬ во всех запросах сразу и упростит индексацию. Но изменение типа реквизита в действующей базе требует реструктуризации, поэтому решение принимают с учётом объёма данных.

Для динамических сценариев, где вид документа заранее неизвестен, приведение типа не подходит — текст запроса пришлось бы генерировать для каждого вида. В таких случаях используют функцию ТИПЗНАЧЕНИЯ для проверки типа либо обрабатывают результат запроса уже в коде, обращаясь к реквизитам через объектную модель.

Наконец, помните о виртуальных таблицах: если нужен отбор по документу в регистре, часто выгоднее сначала ограничить виртуальную таблицу параметрами (период, регистратор), а уже потом приводить типы и соединять. Чем меньше строк попадает в соединение, тем дешевле запрос.

Итог

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

ВЫРАЗИТЬ(Поле КАК Документ.ВидДокумента) сужает составной тип до конкретного документа: открывает доступ к реквизитам через точку и ускоряет соединения. Оператор не фильтрует записи — для несовпадающих видов он возвращает NULL, поэтому отбор добавляйте явно. Перед внедрением проверяйте запрос на копии базы и следите за NULL в группировках.

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

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

Нет, одно выражение ВЫРАЗИТЬ приводит только к одному типу. Если нужно обработать несколько видов, используют несколько приведений с ВЫБОР...КОГДА или несколько левых соединений с разными таблицами документов, а затем собирают реквизит через ЕСТЬNULL или ВЫБОР.

Чем ВЫРАЗИТЬ отличается от проверки ССЫЛКА?

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

Почему после приведения типа все поля документа пустые?

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

Работает ли ВЫРАЗИТЬ в параметрах виртуальных таблиц?

Приведение типа можно использовать в условиях виртуальных таблиц, но эффективнее задавать отборы через штатные параметры (период, регистратор, измерения). Сложные выражения в параметрах виртуальных таблиц часто мешают оптимизатору и замедляют запрос.

Влияет ли приведение типа на скорость запроса?

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

Можно ли использовать ВЫРАЗИТЬ для приведения к строке или числу?

Да, оператор поддерживает и примитивные типы: Число с указанием разрядности, Строка с длиной, Дата, Булево. Это используют, например, чтобы усечь строку неограниченной длины или убрать лишние знаки после запятой. Синтаксис тот же — ВЫРАЗИТЬ(Поле КАК Строка(100)).