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