Приведение типов в языке запросов 1С: когда без ВЫРАЗИТЬ не обойтись

· 10 мин

Содержание

Оператор ВЫРАЗИТЬ(Выражение КАК Тип) в запросе 1С приводит значение поля к указанному типу: строку неограниченной длины — к строке фиксированной длины, составной тип — к одной ссылке, число — к числу нужной разрядности. Пример: ВЫРАЗИТЬ(Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент. Английский вариант того же оператора — CAST(... AS ...).

Выразить значение в запросе 1С нужно в трёх случаях. Первый — сравнить, сгруппировать или упорядочить поле неограниченной длины. Второй — обратиться к реквизиту составного поля без лишних соединений. Третий — округлить число или задать тип пустому полю во временной таблице. Преобразовать число в строку или строку в дату оператор не умеет: это главное, что нужно знать заранее.

Синтаксис ВЫРАЗИТЬ и типы, к которым можно привести

Общая форма:

ВЫРАЗИТЬ(<Выражение> КАК <Тип>)

Тип указывают так же, как в описании реквизитов метаданных:

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

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

Имя типа пишется точно как в дереве метаданных, во множественном числе, если так назван объект: Справочник.Контрагенты, а не Справочник.Контрагент. Опечатка даёт синтаксическую ошибку запроса ещё до выполнения.

После закрывающей скобки можно сразу обращаться к реквизитам приведённой ссылки через точку. Конструктор запроса тоже умеет вставлять этот оператор: в редакторе выражения поля он есть в списке функций.

Строки неограниченной длины: сравнение, группировка, сортировка

Самый частый повод выразить строку в запросе 1С — реквизиты вроде Комментарий или Описание с длиной 0, то есть неограниченные. С ними СУБД работает как с большими текстовыми полями, и платформа запрещает их сравнивать, группировать и сортировать.

Попытка написать ГДЕ Документ.Комментарий = &Текст заканчивается ошибкой:

Нельзя сравнивать поля неограниченной длины и поля несовместимых типов

Решение — привести поле к строке фиксированной длины:

ВЫБРАТЬ
    Реализация.Ссылка,
    ВЫРАЗИТЬ(Реализация.Комментарий КАК СТРОКА(150)) КАК Комментарий
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    ВЫРАЗИТЬ(Реализация.Комментарий КАК СТРОКА(150)) = &Текст

Что происходит при приведении:

  • ✂️ строка длиннее указанной обрезается до первых N символов;
  • 🔍 сравнение идёт уже по обрезанному значению — две разные строки с одинаковым началом окажутся «равными»;
  • 📊 по приведённому полю можно делать СГРУППИРОВАТЬ ПО, УПОРЯДОЧИТЬ ПО, РАЗЛИЧНЫЕ.

В группировке выражение повторяют целиком:

ВЫБРАТЬ
    ВЫРАЗИТЬ(Задачи.Описание КАК СТРОКА(100)) КАК Описание,
    КОЛИЧЕСТВО(*) КАК Количество
ИЗ
    Справочник.Задачи КАК Задачи
СГРУППИРОВАТЬ ПО
    ВЫРАЗИТЬ(Задачи.Описание КАК СТРОКА(100))

Длину берите с запасом под реальные данные. Для поиска по началу текста подойдёт 50–100 символов, для точного совпадения — длина самого длинного значения, которое встречается в базе.

Для ПОДОБНО приводить поле не обязательно: условие Комментарий ПОДОБНО "%возврат%" работает и с неограниченной строкой. Приведение здесь только обрежет текст, и совпадение в конце длинного комментария потеряется.

Альтернатива — ПОДСТРОКА(Комментарий, 1, 150). Результат тот же, но ВЫРАЗИТЬ короче и явно показывает намерение.

Составные типы: Регистратор, Субконто, значения свойств

Поле составного типа хранит ссылку на один из нескольких объектов. Так устроены Регистратор у регистров, Субконто1..3 в бухгалтерских проводках, Значение у дополнительных реквизитов.

Если написать Регистратор.Дата или Субконто1.ИНН, платформа не знает, какую таблицу читать. Она соединяет поле со всеми таблицами из его состава. У регистра с тридцатью видами регистраторов это тридцать левых соединений в одном запросе.

ВЫРАЗИТЬ говорит платформе, какой тип ожидается:

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

Здесь работают в паре два оператора:

  • 🎯 ССЫЛКА отбирает строки, где в поле лежит ссылка нужного типа;
  • 🔗 ВЫРАЗИТЬ даёт доступ к реквизитам этого типа одним соединением.

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

Пример для бухгалтерского регистра — контрагент из первого субконто счёта 62:

ВЫБРАТЬ
    ВЫРАЗИТЬ(Остатки.Субконто1 КАК Справочник.Контрагенты) КАК Контрагент,
    Остатки.СуммаОстатокДт
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&Дата, Счет В ИЕРАРХИИ (&Счет62), , ) КАК Остатки

Тот же приём нужен для значений дополнительных реквизитов: если известно, что свойство «Регион» хранит элемент справочника, приводите Значение к этому справочнику и берите .Наименование.

Соединения и ОБЪЕДИНИТЬ: приведение полей к общему типу

В условии соединения встречаются обе проблемы сразу: составное поле с одной стороны и строка неограниченной длины с другой.

Соединение по составному полю:

ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&Дата, , , ) КАК Остатки
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
    ПО ВЫРАЗИТЬ(Остатки.Субконто1 КАК Справочник.Контрагенты) = Контрагенты.Ссылка

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

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

ВЫБРАТЬ
    Поступление.Ссылка КАК Документ,
    ВЫРАЗИТЬ(NULL КАК Справочник.Контрагенты) КАК Контрагент
ПОМЕСТИТЬ ВТ_Документы
ИЗ
    Документ.ПоступлениеТоваровУслуг КАК Поступление

ОБЪЕДИНИТЬ ВСЕ

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

Зачем это делать:

  • 📐 поле временной таблицы получает явный тип Справочник.Контрагенты;
  • 🔗 через точку от него потом можно брать реквизиты без лишних соединений;
  • 🗂 индекс по такому полю (ИНДЕКСИРОВАТЬ ПО) строится по однотипным данным.

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

Даты и время: что ВЫРАЗИТЬ умеет и чего не умеет

Привести дату к строке вида «01.03.2026» средствами ВЫРАЗИТЬ нельзя. Отформатировать дату внутри запроса тоже нельзя. Оператор работает с датой только как с датой: например, вытаскивает её из составного поля.

ВЫРАЗИТЬ(ЗначенияСвойств.Значение КАК ДАТА)

Для всего остального в языке запросов есть отдельные функции:

ЗадачаФункция
Обрезать время, взять начало дня/месяцаНАЧАЛОПЕРИОДА(Дата, ДЕНЬ), НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ)
Взять конец периодаКОНЕЦПЕРИОДА(Дата, МЕСЯЦ)
Сдвинуть датуДОБАВИТЬКДАТЕ(Дата, ДЕНЬ, 10)
Разница между датамиРАЗНОСТЬДАТ(Дата1, Дата2, ДЕНЬ)
Год, месяц, день как числоГОД(Дата), МЕСЯЦ(Дата), ДЕНЬМЕСЯЦА(Дата)
Дата-константаДАТАВРЕМЯ(2026, 3, 1)

Формат вывода задают там, где данные показывают: в настройках поля схемы компоновки (свойство «Формат») или в коде функцией Формат(Дата, "ДФ=dd.MM.yyyy").

Сравнивать дату со временем и дату без времени удобнее через НАЧАЛОПЕРИОДА(..., ДЕНЬ), а не через границы &Дата и &Дата + 86399. Но в ГДЕ по индексированному полю условие МЕЖДУ &Начало И &Конец быстрее, чем функция над полем.

Числа и точность вычислений

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

ВЫРАЗИТЬ(Товары.Сумма / Товары.Количество КАК ЧИСЛО(15, 2)) КАК Цена

Значение округляется до указанного числа знаков после запятой по арифметическим правилам. Пример: сумма 1000 при количестве 3 даёт 333,333…, после приведения — 333,33. Сумма 1000 при количестве 6 даёт 166,666…, после приведения — 166,67.

Правила, которые избавляют от копеечных расхождений:

  1. Приводите итог вычисления, а не промежуточные слагаемые. ВЫРАЗИТЬ(А * Б / В КАК ЧИСЛО(15, 2)) точнее, чем произведение уже округлённых значений.
  2. Сначала умножайте, потом делите: Сумма * 100 / Итог даёт меньшую погрешность, чем Сумма / Итог * 100.
  3. Длину берите с запасом. Если значение не помещается в ЧИСЛО(10, 2), запрос либо завершится ошибкой, либо вернёт неверный результат — зависит от СУБД. Для сумм обычно хватает ЧИСЛО(15, 2), для количества — ЧИСЛО(15, 3).
  4. Чтобы получить целое, приводите к ЧИСЛО(15, 0). Это округление, а не отбрасывание дробной части: 2,5 станет 3.

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

ВЫБОР
    КОГДА Товары.Количество = 0 ТОГДА 0
    ИНАЧЕ ВЫРАЗИТЬ(Товары.Сумма / Товары.Количество КАК ЧИСЛО(15, 2))
КОНЕЦ КАК Цена

Числа в строку ВЫРАЗИТЬ не переводит: ВЫРАЗИТЬ(Сумма КАК СТРОКА(20)) запрос не примет. Склеивайте текст уже в коде или в макете отчёта.

NULL и пустые значения после приведения

NULL появляется после ВЫРАЗИТЬ в двух ситуациях:

  • 🚫 в составном поле лежит ссылка другого типа, чем указан в операторе;
  • 🕳 исходное значение уже было NULL, например, из левого соединения.

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

Подставить значение вместо NULL помогает ЕСТЬNULL:

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

Для чисел пишут ЕСТЬNULL(ВЫРАЗИТЬ(... КАК ЧИСЛО(15, 2)), 0). Без этого сумма с NULL в выражении Сумма1 + Сумма2 тоже станет NULL.

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

ВЫРАЗИТЬ и скорость запроса

На производительность оператор влияет в обе стороны.

Ускоряет — при обращении к реквизитам составных полей. Вместо соединения со всеми таблицами типа платформа делает одно соединение. На регистрах с десятками видов регистраторов разница заметна в разы, особенно в отчётах за год. Это главная причина, по которой опытные разработчики пишут ВЫРАЗИТЬ(Регистратор КАК ...) даже тогда, когда тип и так понятен из условия.

Замедляет — когда ВЫРАЗИТЬ стоит над полем в ГДЕ или в условии соединения:

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

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

Права доступа на уровне записей (RLS) тоже добавляют соединения по составным полям. Если отчёт тормозит только у пользователей с ограниченными правами, ищите причину в шаблонах ограничений, а не в самом запросе.

Ошибки при использовании ВЫРАЗИТЬ и как их исправить

Диагностика: выберите симптом
Чем ВЫРАЗИТЬ отличается от ССЫЛКА?
ССЫЛКА проверяет, какого типа ссылка лежит в поле, и возвращает Истина или Ложь. ВЫРАЗИТЬ приводит поле к типу и даёт доступ к его реквизитам. Обычно их используют вместе.
Можно ли привести строку к числу в запросе 1С?
Нет. Ни ВЫРАЗИТЬ, ни другие функции языка запросов не разбирают строку в число. Это делают в коде функцией Число() после получения результата.
Нужен ли ВЫРАЗИТЬ, если поле уже одного ссылочного типа?
Нет. Приведение имеет смысл только для составных полей, неограниченных строк и чисел, которые нужно округлить или типизировать.
Работает ли ВЫРАЗИТЬ в схеме компоновки данных?
Да, в тексте запроса набора данных он работает как в обычном запросе. Вычисляемые поля СКД пишутся на языке выражений компоновки, это другой язык, и на него правила запроса не переносите.
Как записать ВЫРАЗИТЬ на английском?
CAST(Поле AS Catalog.Контрагенты). Английский и русский синтаксис можно использовать в любой конфигурации, результат одинаковый.