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

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

1С запрос: ВЫРАЗИТЬ как составной тип — практическое руководство

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

Функция ВЫРАЗИТЬ в языке запросов 1С приводит значение к заданному типу. Чаще всего её применяют к полям составного типа — реквизитам, которые могут хранить ссылки на разные справочники или документы одновременно. Типичный пример: реквизит «Контрагент» с типом «СправочникСсылка.Контрагенты, СправочникСсылка.Организации», или поле «Регистратор» в таблице регистра, которое ссылается на десятки видов документов.

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

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

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

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

Для числа и строки указываются квалификаторы: ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15,2)) или ВЫРАЗИТЬ(Поле КАК СТРОКА(100)). Для даты можно задать состав: ДАТА или ДАТАВРЕМЯ. Квалификаторы важны при сравнениях и при выгрузке результата в таблицу значений — без них точность и длина определяются платформой автоматически.

Пример базового приведения составного реквизита:

ВЫБРАТЬ

ВЫРАЗИТЬ(Расчеты.Контрагент КАК Справочник.Контрагенты) КАК Контрагент,

СУММА(Расчеты.СуммаОстаток) КАК Долг

ИЗ

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

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

ВЫРАЗИТЬ(Расчеты.Контрагент КАК Справочник.Контрагенты)

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

Главный сценарий — реквизит, который может ссылаться на несколько объектов, а вам нужен только один. Например, в регистре сведений «ОтветственныеЛица» реквизит «СтруктурнаяЕдиница» может хранить и организацию, и подразделение. Чтобы получить только организации, пишут:

ВЫБРАТЬ

ВЫРАЗИТЬ(Ответственные.СтруктурнаяЕдиница КАК Справочник.Организации) КАК Организация,

Ответственные.Ответственный КАК Ответственный

ИЗ

РегистрСведений.ОтветственныеЛица КАК Ответственные

ГДЕ

Ответственные.СтруктурнаяЕдиница ССЫЛКА Справочник.Организации

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

Частая ситуация — поле «Регистратор» или «ДокументОснование». Если документ-основание всегда один и тот же вид, приведение к конкретному типу позволяет сразу обращаться к его реквизитам: ВЫРАЗИТЬ(Таб.ДокументОснование КАК Документ.ЗаказКлиента).Склад.

ВЫРАЗИТЬ при соединении таблиц

Соединение по составному полю без приведения заставляет СУБД проверять все таблицы, входящие в составной тип. Приведение поля к одному типу до соединения позволяет использовать индексы целевой таблицы и резко сокращает план запроса:

ВЫБРАТЬ

Движения.Номенклатура КАК Номенклатура,

Контрагенты.Наименование КАК КонтрагентНаименование

ИЗ

РегистрНакопления.Продажи.Обороты КАК Движения

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты

ПО (ВЫРАЗИТЬ(Движения.Контрагент КАК Справочник.Контрагенты) = Контрагенты.Ссылка)

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

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

Если составное поле содержит два-три типа, но по факту в данных используется один, приведение всё равно оправдано: планировщик СУБД строит план по метаданным, а не по фактическому содержимому таблиц.
ПЗ
Практическое замечание

Приведение примитивных типов: строки, числа, даты

Составной примитивный тип встречается реже, но тоже требует приведения. Классический случай — реквизит «Значение» в регистрах сведений дополнительных сведений, где тип может быть и строкой, и числом, и ссылкой. Чтобы сравнить значение с числом, приводят его явно:

ВЫБРАТЬ

ДопСведения.Объект КАК Объект,

ВЫРАЗИТЬ(ДопСведения.Значение КАК ЧИСЛО(15, 3)) КАК ВесНетто

ИЗ

РегистрСведений.ДополнительныеСведения КАК ДопСведения

ГДЕ

ДопСведения.Свойство = &СвойствоВес

И ВЫРАЗИТЬ(ДопСведения.Значение КАК ЧИСЛО(15, 3)) > 0

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

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

Типичные ошибки
01
Использование ВЫРАЗИТЬ вместо отбора: разработчик ждёт, что строки другого типа исчезнут, а получает NULL вместо значения и лишние строки в выборке.
02
Сравнение строк без указания длины: запрос падает с ошибкой, либо длина подбирается платформой и поведение отличается на разных СУБД.
03
Приведение к типу, не входящему в составной тип реквизита: результат всегда NULL, ошибки на этапе проверки запроса может не быть.
04
Двойное приведение одного поля в разных местах запроса с разными типами: усложняет чтение и повышает риск рассинхронизации логики.

ВЫРАЗИТЬ против ССЫЛКА и ВЫБОР: что выбрать

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

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

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

Сравнение вариантов

ВЫРАЗИТЬ + ССЫЛКА в одном запросе

Подходит для большинства задач: отбор по типу и чистое поле для соединений. Минус — логика размазана по тексту запроса.

Временная таблица с приведённым полем

Подходит для сложных пакетных запросов и СКД: приведение делается один раз, дальше везде чистый тип. Минус — больше кода.

ВЫБОР КОГДА ССЫЛКА

Подходит, когда разные типы составного поля обрабатываются по-разному. Минус — громоздко при трёх и более типах.

Пошаговый порядок работы с составным полем

Единый алгоритм помогает не пропустить важные шаги при написании запроса к составному реквизиту.

Порядок действий
  1. 1
    Откройте метаданные реквизита и выясните, какие типы входят в составной тип поля.
  2. 2
    Определите, какие типы реально нужны в результате: один или несколько.
  3. 3
    Добавьте в условие ГДЕ отбор через ССЫЛКА для нужных типов.
  4. 4
    Приведите поле через ВЫРАЗИТЬ к целевому типу в списке полей и в условиях соединений.
  5. 5
    Для строк и чисел укажите квалификаторы: длину строки, точность и разрядность числа.
  6. 6
    Выполните запрос в консоли запросов и проверьте, что NULL появляется только там, где это ожидаемо.
  7. 7
    Проверьте скорость выполнения на реальных данных: план запроса не должен содержать соединений с лишними таблицами составного типа.

Для проверки используйте консоль запросов или конструктор запроса в конфигураторе: конструктор подсвечивает ошибки типов ещё до выполнения. Если запрос работает в отчёте на СКД, дополнительно проверьте, что у приведённого поля появились доступные реквизиты в настройках отбора.

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

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

Поле после ВЫРАЗИТЬ
Норма

Значения нужного типа на месте, NULL только для строк других типов

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

NULL во всех строках — тип в ВЫРАЗИТЬ не совпадает с реальным содержимым

Количество строк
Норма

Совпадает с ожиданием после отбора ССЫЛКА

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

Строки других типов присутствуют — забыто условие отбора

Скорость запроса
Норма

Выполняется без заметной задержки на рабочей базе

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

Замедление после добавления обращения к реквизитам через точку — не хватает приведения перед соединением

Ограничения и частые проблемы

ВЫРАЗИТЬ не умеет преобразовывать значения между несовместимыми типами: строку «123» в число она не превратит. Приведение работает только в рамках типов, реально присутствующих в составном типе поля, либо для сужения квалификаторов примитивов. Попытка привести строковое поле к числу даст ошибку или NULL, но не преобразование.

Вторая группа проблем — производительность при неправильном применении. Если привести поле в условии ГДЕ, но не отобрать строки через ССЫЛКА, СУБД всё равно сканирует все записи. Если приводить поле в каждом соединении большого пакетного запроса вместо однократного приведения во временной таблице, стоимость плана растёт.

Третий нюанс — поведение в иерархических справочниках. Приведение к типу справочника не влияет на проверку иерархии: условия В ИЕРАРХИИ и сравнения с группами продолжают работать так же, как и без приведения.

FAQ

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

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

Почему после ВЫРАЗИТЬ поле стало NULL, хотя значение есть?

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

Нужно ли указывать длину строки в ВЫРАЗИТЬ?

Да, если дальше идёт сравнение, группировка или соединение по этому полю: строки неограниченной длины в таких операциях запрещены. Указывайте длину с запасом относительно реальных данных, иначе значения усечься и могут ложно совпасть.

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

При корректном применении к составному ссылочному полю — ускоряет, потому что исключает лишние таблицы из плана запроса и позволяет использовать индексы целевой таблицы. Само по себе приведение примитивов на скорость почти не влияет.

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

ВЫРАЗИТЬ меняет тип значения в результате запроса, превращая несовпадающие значения в NULL, но не удаляет строки. ССЫЛКА — это проверка типа, которая возвращает Истина или Ложь и используется для отбора строк в условии ГДЕ.

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

Да, конструкция доступна везде, где допустимо выражение: в полях выборки, условиях соединений, условиях ГДЕ, параметрах виртуальных таблиц и в запросах по табличным частям документов.

Итог

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

ВЫРАЗИТЬ приводит составное поле к одному типу: несовпадающие значения становятся NULL, строки не отбрасываются. Для отбора по типу добавляйте условие ССЫЛКА, для строк и чисел указывайте квалификаторы, а в сложных запросах выносите приведение во временную таблицу.